class QtVectorsControls(QtLayerControls):
    """Qt view and controls for the napari Vectors layer.

    Parameters
    ----------
    layer : napari.layers.Vectors
        An instance of a napari Vectors layer.

    Attributes
    ----------
    edge_color_label : qtpy.QtWidgets.QLabel
        Label for edgeColorSwatch
    edgeColorSwatch : qtpy.QtWidgets.QFrame
        Color swatch showing display color of vectors.
    edgeComboBox : qtpy.QtWidgets.QComboBox
        Dropdown widget to select display color for vectors.
    color_mode_comboBox : qtpy.QtWidgets.QComboBox
        Dropdown widget to select edge_color_mode for the vectors.
    color_prop_box : qtpy.QtWidgets.QComboBox
        Dropdown widget to select _edge_color_property for the vectors.
    edge_prop_label : qtpy.QtWidgets.QLabel
        Label for color_prop_box
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : napari.layers.Vectors
        An instance of a napari Vectors layer.
    outOfSliceCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to indicate whether to render out of slice.
    lengthSpinBox : qtpy.QtWidgets.QDoubleSpinBox
        Spin box widget controlling line length of vectors.
        Multiplicative factor on projections for length of all vectors.
    widthSpinBox : qtpy.QtWidgets.QDoubleSpinBox
        Spin box widget controlling edge line width of vectors.
    """

    layer: 'napari.layers.Tracks'

    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.length.connect(self._on_length_change)
        self.layer.events.out_of_slice_display.connect(
            self._on_out_of_slice_display_change)
        self.layer.events.edge_color_mode.connect(
            self._on_edge_color_mode_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)

        # dropdown to select the property for mapping edge_color
        color_properties = self._get_property_values()
        color_prop_box = QComboBox(self)
        color_prop_box.activated[str].connect(self.change_edge_color_property)
        color_prop_box.addItems(color_properties)
        self.color_prop_box = color_prop_box
        self.edge_prop_label = QLabel(trans._('edge property:'))

        # vector direct color mode adjustment and widget
        self.edgeColorEdit = QColorSwatchEdit(
            initial_color=self.layer.edge_color,
            tooltip=trans._('click to set current edge color', ),
        )
        self.edgeColorEdit.color_changed.connect(self.change_edge_color_direct)
        self.edge_color_label = QLabel(trans._('edge color:'))
        self._on_edge_color_change()

        # dropdown to select the edge color mode
        colorModeComboBox = QComboBox(self)
        color_modes = [e.value for e in ColorMode]
        colorModeComboBox.addItems(color_modes)
        colorModeComboBox.activated[str].connect(self.change_edge_color_mode)
        self.color_mode_comboBox = colorModeComboBox
        self._on_edge_color_mode_change()

        # line width in pixels
        self.widthSpinBox = QDoubleSpinBox()
        self.widthSpinBox.setKeyboardTracking(False)
        self.widthSpinBox.setSingleStep(0.1)
        self.widthSpinBox.setMinimum(0.1)
        self.widthSpinBox.setMaximum(np.inf)
        self.widthSpinBox.setValue(self.layer.edge_width)
        self.widthSpinBox.valueChanged.connect(self.change_width)

        # line length
        self.lengthSpinBox = QDoubleSpinBox()
        self.lengthSpinBox.setKeyboardTracking(False)
        self.lengthSpinBox.setSingleStep(0.1)
        self.lengthSpinBox.setValue(self.layer.length)
        self.lengthSpinBox.setMinimum(0.1)
        self.lengthSpinBox.setMaximum(np.inf)
        self.lengthSpinBox.valueChanged.connect(self.change_length)

        out_of_slice_cb = QCheckBox()
        out_of_slice_cb.setToolTip(trans._('Out of slice display'))
        out_of_slice_cb.setChecked(self.layer.out_of_slice_display)
        out_of_slice_cb.stateChanged.connect(self.change_out_of_slice)
        self.outOfSliceCheckBox = out_of_slice_cb

        self.layout().addRow(trans._('opacity:'), self.opacitySlider)
        self.layout().addRow(trans._('width:'), self.widthSpinBox)
        self.layout().addRow(trans._('length:'), self.lengthSpinBox)
        self.layout().addRow(trans._('blending:'), self.blendComboBox)
        self.layout().addRow(trans._('edge color mode:'),
                             self.color_mode_comboBox)
        self.layout().addRow(self.edge_color_label, self.edgeColorEdit)
        self.layout().addRow(self.edge_prop_label, self.color_prop_box)
        self.layout().addRow(trans._('out of slice:'), self.outOfSliceCheckBox)

    def change_edge_color_property(self, property: str):
        """Change edge_color_property of vectors on the layer model.
        This property is the property the edge color is mapped to.

        Parameters
        ----------
        property : str
            property to map the edge color to
        """
        mode = self.layer.edge_color_mode
        try:
            self.layer.edge_color = property
            self.layer.edge_color_mode = mode
        except TypeError:
            # if the selected property is the wrong type for the current color mode
            # the color mode will be changed to the appropriate type, so we must update
            self._on_edge_color_mode_change()
            raise

    def change_edge_color_mode(self, mode: str):
        """Change edge color mode of vectors on the layer model.

        Parameters
        ----------
        mode : str
            Edge color for vectors. Must be: 'direct', 'cycle', or 'colormap'
        """
        old_mode = self.layer.edge_color_mode
        with self.layer.events.edge_color_mode.blocker():
            try:
                self.layer.edge_color_mode = mode
                self._update_edge_color_gui(mode)

            except ValueError:
                # if the color mode was invalid, revert to the old mode
                self.layer.edge_color_mode = old_mode
                raise

    def change_edge_color_direct(self, color: np.ndarray):
        """Change edge color of vectors on the layer model.

        Parameters
        ----------
        color : np.ndarray
            Edge color for vectors, in an RGBA array
        """
        self.layer.edge_color = color

    def change_width(self, value):
        """Change edge line width of vectors on the layer model.

        Parameters
        ----------
        value : float
            Line width of vectors.
        """
        self.layer.edge_width = value
        self.widthSpinBox.clearFocus()
        self.setFocus()

    def change_length(self, value):
        """Change length of vectors on the layer model.

        Multiplicative factor on projections for length of all vectors.

        Parameters
        ----------
        value : float
            Length of vectors.
        """
        self.layer.length = value
        self.lengthSpinBox.clearFocus()
        self.setFocus()

    def change_out_of_slice(self, state):
        """Toggle out of slice display of vectors layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox to indicate whether to render out of slice.
        """
        if state == Qt.Checked:
            self.layer.out_of_slice_display = True
        else:
            self.layer.out_of_slice_display = False

    def _update_edge_color_gui(self, mode: str):
        """Update the GUI element associated with edge_color.
        This is typically used when edge_color_mode changes

        Parameters
        ----------
        mode : str
            The new edge_color mode the GUI needs to be updated for.
            Should be: 'direct', 'cycle', 'colormap'
        """
        if mode in ('cycle', 'colormap'):
            self.edgeColorEdit.setHidden(True)
            self.edge_color_label.setHidden(True)
            self.color_prop_box.setHidden(False)
            self.edge_prop_label.setHidden(False)

        elif mode == 'direct':
            self.edgeColorEdit.setHidden(False)
            self.edge_color_label.setHidden(False)
            self.color_prop_box.setHidden(True)
            self.edge_prop_label.setHidden(True)

    def _get_property_values(self):
        """Get the current property values from the Vectors layer

        Returns
        -------
        property_values : np.ndarray
            array of all of the union of the property names (keys)
            in Vectors.properties and Vectors.property_choices

        """
        property_choices = [*self.layer.property_choices]
        properties = [*self.layer.properties]
        property_values = np.union1d(property_choices, properties)

        return property_values

    def _on_length_change(self):
        """Change length of vectors."""
        with self.layer.events.length.blocker():
            self.lengthSpinBox.setValue(self.layer.length)

    def _on_out_of_slice_display_change(self, event):
        """Receive layer model out_of_slice_display change event and update checkbox."""
        with self.layer.events.out_of_slice_display.blocker():
            self.outOfSliceCheckBox.setChecked(self.layer.out_of_slice_display)

    def _on_edge_width_change(self):
        """Receive layer model width change event and update width spinbox."""
        with self.layer.events.edge_width.blocker():
            self.widthSpinBox.setValue(self.layer.edge_width)

    def _on_edge_color_mode_change(self):
        """Receive layer model edge color mode change event & update dropdown."""
        with qt_signals_blocked(self.color_mode_comboBox):
            mode = self.layer._edge.color_mode
            index = self.color_mode_comboBox.findText(mode,
                                                      Qt.MatchFixedString)
            self.color_mode_comboBox.setCurrentIndex(index)

            self._update_edge_color_gui(mode)

    def _on_edge_color_change(self):
        """Receive layer model edge color  change event & update dropdown."""
        if (self.layer._edge.color_mode == ColorMode.DIRECT
                and len(self.layer.data) > 0):
            with qt_signals_blocked(self.edgeColorEdit):
                self.edgeColorEdit.setColor(self.layer.edge_color[0])
        elif self.layer._edge.color_mode in (
                ColorMode.CYCLE,
                ColorMode.COLORMAP,
        ):
            with qt_signals_blocked(self.color_prop_box):
                prop = self.layer._edge.color_properties.name
                index = self.color_prop_box.findText(prop, Qt.MatchFixedString)
                self.color_prop_box.setCurrentIndex(index)
Beispiel #2
0
class EditGeometryProperties(PyDialog):
    force = True

    def __init__(self, data, win_parent=None):
        """
        +------------------+
        | Edit Actor Props |
        +------------------+------+
        |  Name1                  |
        |  Name2                  |
        |  Name3                  |
        |  Name4                  |
        |                         |
        |  Active_Name    main    |
        |  Color          box     |
        |  Line_Width     2       |
        |  Point_Size     2       |
        |  Bar_Scale      2       |
        |  Opacity        0.5     |
        |  Show/Hide              |
        |                         |
        |    Apply   OK   Cancel  |
        +-------------------------+
        """
        PyDialog.__init__(self, data, win_parent)
        self.set_font_size(data['font_size'])
        del self.out_data['font_size']
        self.setWindowTitle('Edit Geometry Properties')
        self.allow_update = True

        #default
        #self.win_parent = win_parent
        #self.out_data = data

        self.keys = sorted(data.keys())
        self.keys = data.keys()
        keys = self.keys
        #nrows = len(keys)
        self.active_key = 'main'

        items = list(keys)

        header_labels = ['Groups']
        table_model = Model(items, header_labels, self)
        view = SingleChoiceQTableView(self)  #Call your custom QTableView here
        view.setModel(table_model)
        #if qt_version == 4:
        #view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.table = view
        #self.opacity_edit.valueChanged.connect(self.on_opacity)
        #mListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(itemClicked(QListWidgetItem*)));
        #self.table.itemClicked.connect(self.table.mouseDoubleClickEvent)

        actor_obj = data[self.active_key]
        name = actor_obj.name
        line_width = actor_obj.line_width
        point_size = actor_obj.point_size
        bar_scale = actor_obj.bar_scale
        opacity = actor_obj.opacity
        color = actor_obj.color
        show = actor_obj.is_visible
        self.representation = actor_obj.representation

        # table
        header = self.table.horizontalHeader()
        header.setStretchLastSection(True)

        self._default_is_apply = False
        self.name = QLabel("Name:")
        self.name_edit = QLineEdit(str(name))
        self.name_edit.setDisabled(True)

        self.color = QLabel("Color:")
        self.color_edit = QPushButton()
        #self.color_edit.setFlat(True)

        color = self.out_data[self.active_key].color
        qcolor = QtGui.QColor()
        qcolor.setRgb(*color)
        #print('color =%s' % str(color))
        palette = QtGui.QPalette(
            self.color_edit.palette())  # make a copy of the palette
        #palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Base, \
        #qcolor)
        palette.setColor(QtGui.QPalette.Background,
                         QtGui.QColor('blue'))  # ButtonText
        self.color_edit.setPalette(palette)

        self.color_edit.setStyleSheet("QPushButton {"
                                      "background-color: rgb(%s, %s, %s);" %
                                      tuple(color) +
                                      #"border:1px solid rgb(255, 170, 255); "
                                      "}")

        self.use_slider = True
        self.is_opacity_edit_active = False
        self.is_opacity_edit_slider_active = False

        self.is_line_width_edit_active = False
        self.is_line_width_edit_slider_active = False

        self.is_point_size_edit_active = False
        self.is_point_size_edit_slider_active = False

        self.is_bar_scale_edit_active = False
        self.is_bar_scale_edit_slider_active = False

        self.opacity = QLabel("Opacity:")
        self.opacity_edit = QDoubleSpinBox(self)
        self.opacity_edit.setRange(0.1, 1.0)
        self.opacity_edit.setDecimals(1)
        self.opacity_edit.setSingleStep(0.1)
        self.opacity_edit.setValue(opacity)
        if self.use_slider:
            self.opacity_slider_edit = QSlider(QtCore.Qt.Horizontal)
            self.opacity_slider_edit.setRange(1, 10)
            self.opacity_slider_edit.setValue(opacity * 10)
            self.opacity_slider_edit.setTickInterval(1)
            self.opacity_slider_edit.setTickPosition(QSlider.TicksBelow)

        self.line_width = QLabel("Line Width:")
        self.line_width_edit = QSpinBox(self)
        self.line_width_edit.setRange(1, MAX_LINE_WIDTH)
        self.line_width_edit.setSingleStep(1)
        self.line_width_edit.setValue(line_width)
        if self.use_slider:
            self.line_width_slider_edit = QSlider(QtCore.Qt.Horizontal)
            self.line_width_slider_edit.setRange(1, MAX_LINE_WIDTH)
            self.line_width_slider_edit.setValue(line_width)
            self.line_width_slider_edit.setTickInterval(1)
            self.line_width_slider_edit.setTickPosition(QSlider.TicksBelow)

        if self.representation in ['point', 'surface']:
            self.line_width.setEnabled(False)
            self.line_width_edit.setEnabled(False)
            self.line_width_slider_edit.setEnabled(False)

        self.point_size = QLabel("Point Size:")
        self.point_size_edit = QSpinBox(self)
        self.point_size_edit.setRange(1, MAX_POINT_SIZE)
        self.point_size_edit.setSingleStep(1)
        self.point_size_edit.setValue(point_size)
        self.point_size.setVisible(False)
        self.point_size_edit.setVisible(False)
        if self.use_slider:
            self.point_size_slider_edit = QSlider(QtCore.Qt.Horizontal)
            self.point_size_slider_edit.setRange(1, MAX_POINT_SIZE)
            self.point_size_slider_edit.setValue(point_size)
            self.point_size_slider_edit.setTickInterval(1)
            self.point_size_slider_edit.setTickPosition(QSlider.TicksBelow)
            self.point_size_slider_edit.setVisible(False)

        if self.representation in ['wire', 'surface']:
            self.point_size.setEnabled(False)
            self.point_size_edit.setEnabled(False)
            if self.use_slider:
                self.point_size_slider_edit.setEnabled(False)

        self.bar_scale = QLabel("Bar Scale:")
        self.bar_scale_edit = QDoubleSpinBox(self)
        #self.bar_scale_edit.setRange(0.01, 1.0)  # was 0.1
        #self.bar_scale_edit.setRange(0.05, 5.0)
        self.bar_scale_edit.setDecimals(1)
        #self.bar_scale_edit.setSingleStep(bar_scale / 10.)
        self.bar_scale_edit.setSingleStep(0.1)
        self.bar_scale_edit.setValue(bar_scale)

        #if self.use_slider:
        #self.bar_scale_slider_edit = QSlider(QtCore.Qt.Horizontal)
        #self.bar_scale_slider_edit.setRange(1, 100)  # 1/0.05 = 100/5.0
        #self.bar_scale_slider_edit.setValue(opacity * 0.05)
        #self.bar_scale_slider_edit.setTickInterval(10)
        #self.bar_scale_slider_edit.setTickPosition(QSlider.TicksBelow)

        if self.representation != 'bar':
            self.bar_scale.setEnabled(False)
            self.bar_scale_edit.setEnabled(False)
            self.bar_scale.setVisible(False)
            self.bar_scale_edit.setVisible(False)
            #self.bar_scale_slider_edit.setVisible(False)
            #self.bar_scale_slider_edit.setEnabled(False)

        # show/hide
        self.checkbox_show = QCheckBox("Show")
        self.checkbox_hide = QCheckBox("Hide")
        self.checkbox_show.setChecked(show)
        self.checkbox_hide.setChecked(not show)

        if name == 'main':
            self.color.setEnabled(False)
            self.color_edit.setEnabled(False)
            self.point_size.setEnabled(False)
            self.point_size_edit.setEnabled(False)
            if self.use_slider:
                self.point_size_slider_edit.setEnabled(False)

        self.cancel_button = QPushButton("Close")

        self.create_layout()
        self.set_connections()

    def on_delete(self, irow):
        """deletes an actor based on the row number"""
        if irow == 0:  # main
            return
        nkeys = len(self.keys)
        if nkeys in [0, 1]:
            return
        name = self.keys[irow]
        nrows = nkeys - 1
        self.keys.pop(irow)

        header_labels = ['Groups']
        table_model = Model(self.keys, header_labels, self)
        self.table.setModel(table_model)

        if len(self.keys) == 0:
            self.update()
            self.set_as_null()
            return
        if irow == nrows:
            irow -= 1
        new_name = self.keys[irow]
        self.update_active_name(new_name)
        if self.is_gui:
            self.win_parent.delete_actor(name)

    def set_as_null(self):
        """sets the null case"""
        self.name.setVisible(False)
        self.name_edit.setVisible(False)
        self.color.setVisible(False)
        self.color_edit.setVisible(False)
        self.line_width.setVisible(False)
        self.line_width_edit.setVisible(False)
        self.point_size.setVisible(False)
        self.point_size_edit.setVisible(False)
        self.bar_scale.setVisible(False)
        self.bar_scale_edit.setVisible(False)
        self.opacity.setVisible(False)
        self.opacity_edit.setVisible(False)
        self.opacity_slider_edit.setVisible(False)
        self.point_size_slider_edit.setVisible(False)
        self.line_width_slider_edit.setVisible(False)
        self.checkbox_show.setVisible(False)
        self.checkbox_hide.setVisible(False)

    def on_update_geometry_properties_window(self, data):
        """Not Implemented"""
        return
        #new_keys = sorted(data.keys())
        #if self.active_key in new_keys:
        #i = new_keys.index(self.active_key)
        #else:
        #i = 0
        #self.table.update_data(new_keys)
        #self.out_data = data
        #self.update_active_key(i)

    def update_active_key(self, index):
        """
        Parameters
        ----------
        index : PyQt4.QtCore.QModelIndex
            the index of the list

        Internal Parameters
        -------------------
        name : str
            the name of obj
        obj : CoordProperties, AltGeometry
            the storage object for things like line_width, point_size, etc.
        """
        name = str(index.data())
        #print('name = %r' % name)
        #i = self.keys.index(self.active_key)
        self.update_active_name(name)

    def update_active_name(self, name):
        self.active_key = name
        self.name_edit.setText(name)
        obj = self.out_data[name]
        if isinstance(obj, CoordProperties):
            opacity = 1.0
            representation = 'coord'
            is_visible = obj.is_visible
        elif isinstance(obj, AltGeometry):
            line_width = obj.line_width
            point_size = obj.point_size
            bar_scale = obj.bar_scale
            opacity = obj.opacity
            representation = obj.representation
            is_visible = obj.is_visible

            self.color_edit.setStyleSheet(
                "QPushButton {"
                "background-color: rgb(%s, %s, %s);" % tuple(obj.color) +
                #"border:1px solid rgb(255, 170, 255); "
                "}")
            self.allow_update = False
            self.force = False
            self.line_width_edit.setValue(line_width)
            self.point_size_edit.setValue(point_size)
            self.bar_scale_edit.setValue(bar_scale)
            self.force = True
            self.allow_update = True
        else:
            raise NotImplementedError(obj)

        #allowed_representations = [
        #'main', 'surface', 'coord', 'toggle', 'wire', 'point', 'bar']

        if self.representation != representation:
            self.representation = representation
            #if representation not in allowed_representations:
            #msg = 'name=%r; representation=%r is invalid\nrepresentations=%r' % (
            #name, representation, allowed_representations)

            if self.representation == 'coord':
                self.color.setVisible(False)
                self.color_edit.setVisible(False)
                self.line_width.setVisible(False)
                self.line_width_edit.setVisible(False)
                self.point_size.setVisible(False)
                self.point_size_edit.setVisible(False)
                self.bar_scale.setVisible(False)
                self.bar_scale_edit.setVisible(False)
                self.opacity.setVisible(False)
                self.opacity_edit.setVisible(False)
                if self.use_slider:
                    self.opacity_slider_edit.setVisible(False)
                    self.point_size_slider_edit.setVisible(False)
                    self.line_width_slider_edit.setVisible(False)
                    #self.bar_scale_slider_edit.setVisible(False)
            else:
                self.color.setVisible(True)
                self.color_edit.setVisible(True)
                self.line_width.setVisible(True)
                self.line_width_edit.setVisible(True)
                self.point_size.setVisible(True)
                self.point_size_edit.setVisible(True)
                self.bar_scale.setVisible(True)
                #self.bar_scale_edit.setVisible(True)
                self.opacity.setVisible(True)
                self.opacity_edit.setVisible(True)
                if self.use_slider:
                    self.opacity_slider_edit.setVisible(True)
                    self.line_width_slider_edit.setVisible(True)
                    self.point_size_slider_edit.setVisible(True)
                    #self.bar_scale_slider_edit.setVisible(True)

                if name == 'main':
                    self.color.setEnabled(False)
                    self.color_edit.setEnabled(False)
                    self.point_size.setEnabled(False)
                    self.point_size_edit.setEnabled(False)
                    self.line_width.setEnabled(True)
                    self.line_width_edit.setEnabled(True)
                    self.bar_scale.setEnabled(False)
                    self.bar_scale_edit.setEnabled(False)
                    show_points = False
                    show_line_width = True
                    show_bar_scale = False
                    if self.use_slider:
                        self.line_width_slider_edit.setEnabled(True)
                        #self.bar_scale_slider_edit.setVisible(False)
                else:
                    self.color.setEnabled(True)
                    self.color_edit.setEnabled(True)

                    show_points = False
                    if self.representation in ['point', 'wire+point']:
                        show_points = True

                    show_line_width = False
                    if self.representation in [
                            'wire', 'wire+point', 'bar', 'toggle'
                    ]:
                        show_line_width = True

                    if representation == 'bar':
                        show_bar_scale = True
                    else:
                        show_bar_scale = False
                    #self.bar_scale_button.setVisible(show_bar_scale)
                    #self.bar_scale_edit.setSingleStep(bar_scale / 10.)
                    #if self.use_slider:
                    #self.bar_scale_slider_edit.setEnabled(False)

                self.point_size.setEnabled(show_points)
                self.point_size_edit.setEnabled(show_points)
                self.point_size.setVisible(show_points)
                self.point_size_edit.setVisible(show_points)

                self.line_width.setEnabled(show_line_width)
                self.line_width_edit.setEnabled(show_line_width)

                self.bar_scale.setEnabled(show_bar_scale)
                self.bar_scale_edit.setEnabled(show_bar_scale)
                self.bar_scale.setVisible(show_bar_scale)
                self.bar_scale_edit.setVisible(show_bar_scale)
                if self.use_slider:
                    self.point_size_slider_edit.setEnabled(show_points)
                    self.point_size_slider_edit.setVisible(show_points)
                    self.line_width_slider_edit.setEnabled(show_line_width)

            #if self.representation in ['wire', 'surface']:

        self.opacity_edit.setValue(opacity)
        #if self.use_slider:
        #self.opacity_slider_edit.setValue(opacity*10)
        self.checkbox_show.setChecked(is_visible)
        self.checkbox_hide.setChecked(not is_visible)

        passed = self.on_validate()
        #self.on_apply(force=True)  # TODO: was turned on...do I want this???
        #self.allow_update = True

    def create_layout(self):
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.cancel_button)

        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.name, irow, 0)
        grid.addWidget(self.name_edit, irow, 1)
        irow += 1

        grid.addWidget(self.color, irow, 0)
        grid.addWidget(self.color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.opacity, irow, 0)
        if self.use_slider:
            grid.addWidget(self.opacity_edit, irow, 2)
            grid.addWidget(self.opacity_slider_edit, irow, 1)
        else:
            grid.addWidget(self.opacity_edit, irow, 1)
        irow += 1

        grid.addWidget(self.line_width, irow, 0)
        if self.use_slider:
            grid.addWidget(self.line_width_edit, irow, 2)
            grid.addWidget(self.line_width_slider_edit, irow, 1)
        else:
            grid.addWidget(self.line_width_edit, irow, 1)
        irow += 1

        grid.addWidget(self.point_size, irow, 0)
        if self.use_slider:
            grid.addWidget(self.point_size_edit, irow, 2)
            grid.addWidget(self.point_size_slider_edit, irow, 1)
        else:
            grid.addWidget(self.point_size_edit, irow, 1)
        irow += 1

        grid.addWidget(self.bar_scale, irow, 0)
        if self.use_slider and 0:
            grid.addWidget(self.bar_scale_edit, irow, 2)
            grid.addWidget(self.bar_scale_slider_edit, irow, 1)
        else:
            grid.addWidget(self.bar_scale_edit, irow, 1)
        irow += 1

        checkboxs = QButtonGroup(self)
        checkboxs.addButton(self.checkbox_show)
        checkboxs.addButton(self.checkbox_hide)

        vbox = QVBoxLayout()
        vbox.addWidget(self.table, stretch=1)
        vbox.addLayout(grid)

        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.checkbox_show)
        vbox1.addWidget(self.checkbox_hide)
        vbox.addLayout(vbox1)

        vbox.addStretch()
        #vbox.addWidget(self.check_apply)
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        self.opacity_edit.valueChanged.connect(self.on_opacity)
        self.line_width_edit.valueChanged.connect(self.on_line_width)
        self.point_size_edit.valueChanged.connect(self.on_point_size)
        self.bar_scale_edit.valueChanged.connect(self.on_bar_scale)

        if self.use_slider:
            self.opacity_slider_edit.valueChanged.connect(
                self.on_opacity_slider)
            self.line_width_slider_edit.valueChanged.connect(
                self.on_line_width_slider)
            self.point_size_slider_edit.valueChanged.connect(
                self.on_point_size_slider)
            #self.bar_scale_slider_edit.valueChanged.connect(self.on_bar_scale_slider)

        # self.connect(self.opacity_edit, QtCore.SIGNAL('clicked()'), self.on_opacity)
        # self.connect(self.line_width, QtCore.SIGNAL('clicked()'), self.on_line_width)
        # self.connect(self.point_size, QtCore.SIGNAL('clicked()'), self.on_point_size)

        if qt_version == 4:
            self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent)
        self.color_edit.clicked.connect(self.on_color)
        self.checkbox_show.clicked.connect(self.on_show)
        self.checkbox_hide.clicked.connect(self.on_hide)
        self.cancel_button.clicked.connect(self.on_cancel)
        # closeEvent

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.close()

    def closeEvent(self, event):
        self.on_cancel()

    def on_color(self):
        """called when the user clicks on the color box"""
        name = self.active_key
        obj = self.out_data[name]
        rgb_color_ints = obj.color

        msg = name
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    "Choose a %s color" % msg)
        if col.isValid():
            color_float = col.getRgbF()[:3]
            obj.color = color_float
            color_int = [int(colori * 255) for colori in color_float]
            self.color_edit.setStyleSheet(
                "QPushButton {"
                "background-color: rgb(%s, %s, %s);" % tuple(color_int) +
                #"border:1px solid rgb(255, 170, 255); "
                "}")
        self.on_apply(force=self.force)
        #print(self.allow_update)

    def on_show(self):
        """shows the actor"""
        name = self.active_key
        is_checked = self.checkbox_show.isChecked()
        self.out_data[name].is_visible = is_checked
        self.on_apply(force=self.force)

    def on_hide(self):
        """hides the actor"""
        name = self.active_key
        is_checked = self.checkbox_hide.isChecked()
        self.out_data[name].is_visible = not is_checked
        self.on_apply(force=self.force)

    def on_line_width(self):
        """increases/decreases the wireframe (for solid bodies) or the bar thickness"""
        self.is_line_width_edit_active = True
        name = self.active_key
        line_width = self.line_width_edit.value()
        self.out_data[name].line_width = line_width
        if not self.is_line_width_edit_slider_active:
            if self.use_slider:
                self.line_width_slider_edit.setValue(line_width)
            self.is_line_width_edit_active = False
        self.on_apply(force=self.force)
        self.is_line_width_edit_active = False

    def on_line_width_slider(self):
        """increases/decreases the wireframe (for solid bodies) or the bar thickness"""
        self.is_line_width_edit_slider_active = True
        #name = self.active_key
        line_width = self.line_width_slider_edit.value()
        if not self.is_line_width_edit_active:
            self.line_width_edit.setValue(line_width)
        self.is_line_width_edit_slider_active = False

    def on_point_size(self):
        """increases/decreases the point size"""
        self.is_point_size_edit_active = True
        name = self.active_key
        point_size = self.point_size_edit.value()
        self.out_data[name].point_size = point_size
        if not self.is_point_size_edit_slider_active:
            if self.use_slider:
                self.point_size_slider_edit.setValue(point_size)
            self.is_point_size_edit_active = False
        self.on_apply(force=self.force)
        self.is_point_size_edit_active = False

    def on_point_size_slider(self):
        """increases/decreases the point size"""
        self.is_point_size_edit_slider_active = True
        #name = self.active_key
        point_size = self.point_size_slider_edit.value()
        if not self.is_point_size_edit_active:
            self.point_size_edit.setValue(point_size)
        self.is_point_size_edit_slider_active = False

    def on_bar_scale(self):
        """
        Vectors start at some xyz coordinate and can increase in length.
        Increases/decreases the length scale factor.
        """
        self.is_bar_scale_edit_active = True
        name = self.active_key
        float_bar_scale = self.bar_scale_edit.value()
        self.out_data[name].bar_scale = float_bar_scale
        if not self.is_bar_scale_edit_slider_active:
            #int_bar_scale = int(round(float_bar_scale * 20, 0))
            #if self.use_slider:
            #self.bar_scale_slider_edit.setValue(int_bar_scale)
            self.is_bar_scale_edit_active = False
        self.on_apply(force=self.force)
        self.is_bar_scale_edit_active = False

    def on_bar_scale_slider(self):
        """
        Vectors start at some xyz coordinate and can increase in length.
        Increases/decreases the length scale factor.
        """
        self.is_bar_scale_edit_slider_active = True
        #name = self.active_key
        int_bar_scale = self.bar_scale_slider_edit.value()
        if not self.is_bar_scale_edit_active:
            float_bar_scale = int_bar_scale / 20.
            self.bar_scale_edit.setValue(float_bar_scale)
        self.is_bar_scale_edit_slider_active = False

    def on_opacity(self):
        """
        opacity = 1.0 (solid/opaque)
        opacity = 0.0 (invisible)
        """
        self.is_opacity_edit_active = True
        name = self.active_key
        float_opacity = self.opacity_edit.value()
        self.out_data[name].opacity = float_opacity
        if not self.is_opacity_edit_slider_active:
            int_opacity = int(round(float_opacity * 10, 0))
            if self.use_slider:
                self.opacity_slider_edit.setValue(int_opacity)
            self.is_opacity_edit_active = False
        self.on_apply(force=self.force)
        self.is_opacity_edit_active = False

    def on_opacity_slider(self):
        """
        opacity = 1.0 (solid/opaque)
        opacity = 0.0 (invisible)
        """
        self.is_opacity_edit_slider_active = True
        #name = self.active_key
        int_opacity = self.opacity_slider_edit.value()
        if not self.is_opacity_edit_active:
            float_opacity = int_opacity / 10.
            self.opacity_edit.setValue(float_opacity)
        self.is_opacity_edit_slider_active = False

    def on_validate(self):
        self.out_data['clicked_ok'] = True
        self.out_data['clicked_cancel'] = False

        old_obj = self.out_data[self.active_key]
        old_obj.line_width = self.line_width_edit.value()
        old_obj.point_size = self.point_size_edit.value()
        old_obj.bar_scale = self.bar_scale_edit.value()
        old_obj.opacity = self.opacity_edit.value()
        #old_obj.color = self.color_edit
        old_obj.is_visible = self.checkbox_show.isChecked()
        return True
        #name_value, flag0 = self.check_name(self.name_edit)
        #ox_value, flag1 = self.check_float(self.transparency_edit)
        #if flag0 and flag1:
        #self.out_data['clicked_ok'] = True
        #return True
        #return False

    @property
    def is_gui(self):
        return hasattr(self.win_parent, 'on_update_geometry_properties')

    def on_apply(self, force=False):
        passed = self.on_validate()
        #print("passed=%s force=%s allow=%s" % (passed, force, self.allow_update))
        if (passed or force) and self.allow_update and self.is_gui:
            #print('obj = %s' % self.out_data[self.active_key])
            self.win_parent.on_update_geometry_properties(self.out_data,
                                                          name=self.active_key)
        return passed

    def on_cancel(self):
        passed = self.on_apply(force=True)
        if passed:
            self.close()
Beispiel #3
0
class ERDSDialog(QDialog):
    def __init__(self, parent, t_range, f_range):
        super().__init__(parent)
        self.setWindowTitle("ERDS maps")
        vbox = QVBoxLayout(self)
        grid = QGridLayout()

        grid.addWidget(QLabel("Frequency range:"), 0, 0)
        self._f1 = QDoubleSpinBox()
        self._f1.setRange(*f_range)
        self._f1.setValue(f_range[0])
        self._f1.setDecimals(1)
        self._f1.setSuffix(" Hz")
        grid.addWidget(self._f1, 0, 1)

        self._f2 = QDoubleSpinBox()
        self._f2.setRange(*f_range)
        self._f2.setValue(f_range[1])
        self._f2.setDecimals(1)
        self._f2.setSuffix(" Hz")
        grid.addWidget(self._f2, 0, 2)

        grid.addWidget(QLabel("Step size:"), 1, 0)
        self._step = QDoubleSpinBox()
        self._step.setRange(0.1, 5)
        self._step.setValue(1)
        self._step.setDecimals(1)
        self._step.setSingleStep(0.1)
        self._step.setSuffix(" Hz")
        grid.addWidget(self._step, 1, 1)

        grid.addWidget(QLabel("Time range:"), 2, 0)
        self._t1 = QDoubleSpinBox()
        self._t1.setRange(*t_range)
        self._t1.setValue(t_range[0])
        self._t1.setDecimals(1)
        self._step.setSingleStep(0.1)
        self._t1.setSuffix(" s")
        grid.addWidget(self._t1, 2, 1)

        self._t2 = QDoubleSpinBox()
        self._t2.setRange(*t_range)
        self._t2.setValue(t_range[1])
        self._t2.setDecimals(1)
        self._step.setSingleStep(0.1)
        self._t2.setSuffix(" s")
        grid.addWidget(self._t2, 2, 2)

        grid.addWidget(QLabel("Baseline:"), 3, 0)
        self._b1 = QDoubleSpinBox()
        self._b1.setRange(*t_range)
        self._b1.setValue(t_range[0])
        self._b1.setDecimals(1)
        self._step.setSingleStep(0.1)
        self._b1.setSuffix(" s")
        grid.addWidget(self._b1, 3, 1)

        self._b2 = QDoubleSpinBox()
        self._b2.setRange(*t_range)
        self._b2.setValue(0)
        self._b2.setDecimals(1)
        self._step.setSingleStep(0.1)
        self._b2.setSuffix(" s")
        grid.addWidget(self._b2, 3, 2)

        vbox.addLayout(grid)
        buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        vbox.addWidget(buttonbox)
        buttonbox.accepted.connect(self.accept)
        buttonbox.rejected.connect(self.reject)
        vbox.setSizeConstraint(QVBoxLayout.SetFixedSize)

    @property
    def f1(self):
        return self._f1.value()

    @property
    def f2(self):
        return self._f2.value()

    @property
    def step(self):
        return self._step.value()

    @property
    def t1(self):
        return self._t1.value()

    @property
    def t2(self):
        return self._t2.value()

    @property
    def b1(self):
        return self._b1.value()

    @property
    def b2(self):
        return self._b2.value()
Beispiel #4
0
class BreakSurfaceMenu(QDialog):
    def __init__(self, data, win_parent=None):
        """
        +-----------------+
        | Break Surfaces  |
        +-----------------+------+
        |  EngineInlet           |
        |  EngineOutlet          |
        |                        |
        |  Name      EngineInlet |
        |  RegionMode * RegionID |
        |             * All      |
        |                        |
        |  AllowedRegions:       |
        |    Region ID      3    |
        |                        |
        |  PickMode  * All       |
        |  Pick Mode  x On/Off   |
        |  Pick Angle   20 deg   |
        |                        |
        |         Revert         |
        |     RenumberRegions    |
        |         Close          |
        +------------------------+
        """
        QDialog.__init__(self, win_parent)
        self.setWindowTitle('Break Surface')

        #default
        self.win_parent = win_parent
        self.out_data = data

        self.points = data['points']

        self.keys = sorted(self.points.keys())
        keys = self.keys
        nrows = len(keys)

        active_point = data['active_point']
        #self.active_key = keys[0]
        self.active_key = active_point
        name = self.active_key
        description = self.points[self.active_key][0]

        self._use_old_table = False
        items = ['Node %i' % val for val in keys]
        header_labels = ['Nodes']
        table_model = Model(items, header_labels, self)
        view = SingleChoiceQTableView(self)  #Call your custom QTableView here
        view.setModel(table_model)

        header = view.horizontalHeader()
        header.setSectionResizeMode(0, QHeaderView.Stretch)
        #header.setResizeMode(QtGui.QHeaderView.Stretch)
        self.table = view

        #self.representation = actor_obj.representation
        #print('rep =', self.representation)

        table = self.table
        #headers = [QtCore.QString('Groups')]

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        #----------------------------------------------
        #self._default_is_apply = False

        self.mode_header = QLabel("Mode:")

        nregions_max = 10
        pick_angle = 20.0
        region_id = 4
        all_regions = True
        self.region_id = QLabel("Region ID:")
        self.region_id_edit = QSpinBox(self)
        self.region_id_edit.setRange(1, nregions_max)
        self.region_id_edit.setSingleStep(1)
        self.region_id_edit.setValue(region_id)

        self.pick_angle = QLabel("Pick Angle:")
        self.pick_angle_edit = QDoubleSpinBox(self)
        self.pick_angle_edit.setRange(0.0, 360.0)
        self.pick_angle_edit.setDecimals(3)
        self.pick_angle_edit.setSingleStep(0.5)
        self.pick_angle_edit.setValue(pick_angle)

        # region IDs/all
        self.checkbox_region_ids = QCheckBox("Region IDs")
        self.checkbox_region_all = QCheckBox("All Regions")
        self.checkbox_region_all.setChecked(all_regions)
        self.checkbox_region_ids.setChecked(not all_regions)

        # pick mode
        self.checkbox_pick_mode = QCheckBox("Pick Mode  (Off=label)")
        self.checkbox_pick_mode.setChecked(False)

        #----------------------------------------------
        self.nodes_header = QLabel("Single Node:")
        self.name = QLabel("ID:")
        self.name_edit = QLineEdit('Node %i' % name)
        self.name_edit.setDisabled(True)

        #----------------------------------------------
        self.location_x = QLabel("X:")
        self.location_x_edit = QLineEdit('X')

        self.location_y = QLabel("Y:")
        self.location_y_edit = QLineEdit('Y')

        self.location_z = QLabel("Z:")
        self.location_z_edit = QLineEdit('Z')

        #----------------------------------------------

        # remove these...
        self.description_edit = QLineEdit('Description')
        self.coord_edit = QSpinBox()

        #----------------------------------------------

        # closing
        #if self._default_is_apply:
        #self.apply_button.setDisabled(True)

        self.close_button = QPushButton("Close")

        self.create_layout()
        #self.set_connections()

    def update_active_key(self, index):
        name = self.active_key
        old_obj = self.out_data['points'][name]
        #self.active_key
        #self.points[self.active_key]
        old_obj[0] = str(self.description_edit.text())
        #old_obj.coord = self.description_edit.value()
        #old_obj.description = self.description_edit.value()
        #old_obj.description = self.description_edit.value()

        str_name = str(index.data())
        name = int(str_name[5:])
        #i = self.keys.index(self.active_key)

        self.active_key = name
        point = self.points[self.active_key]

        #1  : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        self.name_edit.setText(str(self.active_key))
        self.description_edit.setText(point[0])

        self.coord_edit.setValue(point[1])
        if point[2] == 'R':
            self.radio_rectangular.setChecked(True)
        elif point[2] == 'C':
            self.radio_cylindrical.setChecked(True)
        elif point[2] == 'S':
            self.radio_spherical.setChecked(True)

        self.location_x_edit.setText(str(point[3]))
        self.location_y_edit.setText(str(point[4]))
        self.location_z_edit.setText(str(point[5]))
        #obj = self.out_data[name]
        #point_size = obj.point_size
        #opacity = obj.opacity
        #representation = obj.representation
        #is_visible = obj.is_visible

        #self.opacity_edit.setValue(opacity)
        #self.checkbox_show.setChecked(is_visible)
        #self.checkbox_hide.setChecked(not is_visible)

    #def on_name_select(self):
    #print('on_name_select')
    #return

    def create_layout(self):
        cancel_box = QHBoxLayout()
        cancel_box.addWidget(self.close_button)

        grid1 = QGridLayout()
        grid2 = QGridLayout()

        #-----------------------------------------
        # setup
        self.radio_rectangular = QRadioButton('Rectangular')
        self.radio_cylindrical = QRadioButton('Cylindrical')
        self.radio_spherical = QRadioButton('Spherical')

        coord_type_layout = QHBoxLayout()
        coord_type_layout.addWidget(self.radio_rectangular)
        coord_type_layout.addWidget(self.radio_cylindrical)
        coord_type_layout.addWidget(self.radio_spherical)

        checkboxs = QButtonGroup(self)
        checkboxs.addButton(self.checkbox_region_all)
        checkboxs.addButton(self.checkbox_region_ids)

        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.checkbox_region_all)
        vbox1.addWidget(self.checkbox_region_ids)
        #vbox1.addLayout(checkboxs)

        #-----------------------------------------
        irow = 0
        grid2.addWidget(self.name, irow, 0)
        grid2.addWidget(self.name_edit, irow, 1)
        irow += 1

        #grid2.addWidget(self.name, irow, 0)
        grid2.addWidget(self.description_edit, irow, 1)
        irow += 1

        grid2.addWidget(self.location_x, irow, 0)
        grid2.addWidget(self.location_x_edit, irow, 1)
        irow += 1

        grid2.addWidget(self.location_y, irow, 0)
        grid2.addWidget(self.location_y_edit, irow, 1)
        irow += 1

        grid2.addWidget(self.location_z, irow, 0)
        grid2.addWidget(self.location_z_edit, irow, 1)
        irow += 1

        #|  Name      EngineInlet |
        #|  RegionMode * RegionID |
        #|             * All      |
        #|                        |
        #|  AllowedRegions:       |
        #|    Region ID      3    |
        #|                        |
        #|  PickMode  * All       |
        #|  Pick Mode  x On/Off   |
        #|  Pick Angle   20 deg   |
        #|                        |
        #|         Revert         |
        #|     RenumberRegions    |
        #|         Close          |

        grid2.addWidget(self.region_id, irow, 0)
        grid2.addWidget(self.region_id_edit, irow, 1)
        irow += 1

        #grid2.addWidget(self.pick_mode, irow, 0)
        grid2.addWidget(self.checkbox_pick_mode, irow, 0)
        irow += 1

        grid2.addWidget(self.pick_angle, irow, 0)
        grid2.addWidget(self.pick_angle_edit, irow, 1)
        irow += 1

        #grid2.addWidget(self.pi, irow, 0)
        #grid2.addLayout(coord_type_layout, irow, 1)
        #irow += 1

        #grid2.addWidget(self.location, irow, 0)
        #grid2.addLayout(location_layout, irow, 1)
        #irow += 1

        #------------------------------------

        vbox = QVBoxLayout()
        vbox.addLayout(grid1)
        #vbox.addLayout(vbox1)
        #vbox.addStretch()
        vbox.addWidget(self.table)

        vbox.addLayout(grid2)
        vbox.addStretch()
        #vbox.addWidget(self.check_apply)
        vbox.addLayout(cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        self.opacity_edit.clicked.connect(self.on_opacity)
        self.point_size.clicked.connect(self.on_point_size)
        self.color_edit.clicked.connect(self.on_color)
        self.checkbox_show.clicked.connect(self.on_show)
        self.checkbox_hide.clicked.connect(self.on_hide)

        #self.connect(self.description_edit, QtCore.SIGNAL("valueChanged(int)"), self.on_description)
        #self.connect(self.coord_edit, QtCore.SIGNAL("valueChanged(int)"), self.on_coord)
        self.radio_rectangular.clicked.connect(self.on_coord_type)
        self.radio_cylindrical.clicked.connect(self.on_coord_type)
        self.radio_spherical.clicked.connect(self.on_coord_type)

        self.location_x_edit.clicked.connect(self.on_location_x)
        self.location_y_edit.clicked.connect(self.on_location_y)
        self.location_z_edit.clicked.connect(self.on_location_z)

        self.close_button.clicked.connect(self.on_close)

        #self.connect(self.check_apply, QtCore.SIGNAL('clicked()'), self.on_check_apply)

        #self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
        #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
        self.close_button.clicked.connect(self.on_close)

    def on_color(self):
        obj = self.out_data['point_properties']
        rgb_color_ints = obj.color

        msg = 'Points'
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    "Choose a %s color" % msg)
        if col.isValid():
            color = col.getRgbF()[:3]
            obj.color = color
            #print('new_color =', color)
            self.color_edit.setStyleSheet(
                "QPushButton {"
                "background-color: rgb(%s, %s, %s);" % tuple(obj.color) +
                #"border:1px solid rgb(255, 170, 255); "
                "}")

    def on_show(self):
        is_checked = self.checkbox_show.isChecked()
        self.out_data['point_properties'].is_visible = is_checked

    def on_hide(self):
        is_checked = self.checkbox_hide.isChecked()
        self.out_data['point_properties'].is_visible = not is_checked

    def on_point_size(self):
        point_size = self.point_size_edit.value()
        self.out_data['point_properties'].point_size = point_size

    def on_opacity(self):
        opacity = self.opacity_edit.value()
        self.out_data['point_properties'].opacity = opacity

    def on_description(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        description = self.description_edit.value()
        self.out_data['points'][name][0] = description

    def on_coord(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        coord_id = self.coord_edit.value()
        self.out_data['points'][name][1] = coord_id

    def on_coord_type(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        if self.radio_rectangular.isChecked():
            coord_type = 'R'
        elif self.radio_cylindrical.isChecked():
            coord_type = 'C'
        elif self.radio_spherical.isChecked():
            coord_type = 'S'
        else:
            raise NotImplementedError()
        self.out_data['points'][name][2] = coord_type

    def on_location_x(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][3] = value

    def on_location_y(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][4] = value

    def on_location_z(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][5] = value

    def closeEvent(self, event):
        event.accept()

    #def on_default_name(self):
    #self.name_edit.setText(str(self._default_name))
    #self.name_edit.setStyleSheet("QLineEdit{background: white;}")

    #def check_float(self, cell):
    #text = cell.text()
    #try:
    #value = eval_float_from_string(text)
    #cell.setStyleSheet("QLineEdit{background: white;}")
    #return value, True
    #except ValueError:
    #cell.setStyleSheet("QLineEdit{background: red;}")
    #return None, False

    #def check_name(self, cell):
    #text = str(cell.text()).strip()
    #if len(text):
    #cell.setStyleSheet("QLineEdit{background: white;}")
    #return text, True
    #else:
    #cell.setStyleSheet("QLineEdit{background: red;}")
    #return None, False

    def on_validate(self):
        self.out_data['clicked_ok'] = True
        self.out_data['clicked_cancel'] = False

        old_obj = self.out_data[self.active_key]
        old_obj.point_size = self.point_size_edit.value()
        old_obj.opacity = self.opacity_edit.value()
        old_obj.is_visible = self.checkbox_show.isChecked()
        return True
        #name_value, flag0 = self.check_name(self.name_edit)
        #ox_value, flag1 = self.check_float(self.transparency_edit)
        #if flag0 and flag1:
        #self.out_data['clicked_ok'] = True
        #return True
        #return False

    def on_apply(self):
        passed = self.on_validate()
        if passed:
            self.win_parent.on_update_gui_nodes(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_close(self):
        self.out_data['clicked_close'] = True
        self.close()
Beispiel #5
0
class StyleChooser(QWidget):
    def __init__(self, line_style_set=STYLESET_DEFAULT):
        QWidget.__init__(self)
        self._style = PlotStyle("StyleChooser Internal Style")

        self._styles = STYLES[
            'default'] if not line_style_set in STYLES else STYLES[
                line_style_set]

        self.setMinimumWidth(140)
        self.setMaximumHeight(25)

        layout = QHBoxLayout()

        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(2)

        self.line_chooser = QComboBox()
        self.line_chooser.setToolTip("Select line style.")
        for style in self._styles:
            self.line_chooser.addItem(*style)

        self.marker_chooser = QComboBox()
        self.marker_chooser.setToolTip("Select marker style.")
        for marker in MARKERS:
            self.marker_chooser.addItem(*marker)

        self.thickness_spinner = QDoubleSpinBox()
        self.thickness_spinner.setToolTip("Line thickness")
        self.thickness_spinner.setMinimum(0.1)
        self.thickness_spinner.setDecimals(1)
        self.thickness_spinner.setSingleStep(0.1)

        self.size_spinner = QDoubleSpinBox()
        self.size_spinner.setToolTip("Marker Size")
        self.size_spinner.setMinimum(0.1)
        self.size_spinner.setDecimals(1)
        self.size_spinner.setSingleStep(0.1)

        # the text content of the spinner varies, but shouldn't push the control out of boundaries
        self.line_chooser.setMinimumWidth(110)
        layout.addWidget(self.line_chooser)
        layout.addWidget(self.thickness_spinner)
        layout.addWidget(self.marker_chooser)
        layout.addWidget(self.size_spinner)

        self.setLayout(layout)

        self.line_chooser.currentIndexChanged.connect(self._updateStyle)
        self.marker_chooser.currentIndexChanged.connect(self._updateStyle)
        self.thickness_spinner.valueChanged.connect(self._updateStyle)
        self.size_spinner.valueChanged.connect(self._updateStyle)

        self._updateLineStyleAndMarker(self._style.line_style,
                                       self._style.marker, self._style.width,
                                       self._style.size)
        self._layout = layout

    def getItemSizes(self):
        line_style_combo_width = self._layout.itemAt(0).sizeHint().width()
        thickness_spinner_width = self._layout.itemAt(1).sizeHint().width()
        marker_combo_width = self._layout.itemAt(2).sizeHint().width()
        size_spinner_width = self._layout.itemAt(3).sizeHint().width()
        return line_style_combo_width, thickness_spinner_width, marker_combo_width, size_spinner_width

    def _findLineStyleIndex(self, line_style):
        for index, style in enumerate(self._styles):
            if style[1] == line_style:
                return index
            elif style[1] is None and line_style == "":
                return index
        return -1

    def _findMarkerStyleIndex(self, marker):
        for index, style in enumerate(MARKERS):
            if style[1] == marker:
                return index
            elif style[1] is None and marker == "":
                return index
        return -1

    def _updateLineStyleAndMarker(self, line_style, marker, thickness, size):
        self.line_chooser.setCurrentIndex(self._findLineStyleIndex(line_style))
        self.marker_chooser.setCurrentIndex(self._findMarkerStyleIndex(marker))
        self.thickness_spinner.setValue(thickness)
        self.size_spinner.setValue(size)

    def _updateStyle(self):
        self.marker_chooser.setEnabled(
            self.line_chooser.currentText() != "Area")

        line_style = self.line_chooser.itemData(
            self.line_chooser.currentIndex())
        marker_style = self.marker_chooser.itemData(
            self.marker_chooser.currentIndex())
        thickness = float(self.thickness_spinner.value())
        size = float(self.size_spinner.value())

        self._style.line_style = line_style
        self._style.marker = marker_style
        self._style.width = thickness
        self._style.size = size

    def setStyle(self, style):
        """ @type style: PlotStyle """
        self._style.copyStyleFrom(style)
        self._updateLineStyleAndMarker(style.line_style, style.marker,
                                       style.width, style.size)

    def getStyle(self):
        """ @rtype: PlotStyle """
        style = PlotStyle("Generated Style from StyleChooser")
        style.copyStyleFrom(self._style)
        return style

    def createLabelLayout(self, layout=None):
        if layout is None:
            layout = QHBoxLayout()

        titles = ["Line Style", "Width", "Marker Style", "Size"]
        sizes = self.getItemSizes()
        for title, size in zip(titles, sizes):
            label = QLabel(title)
            label.setFixedWidth(size)
            layout.addWidget(label)

        return layout
Beispiel #6
0
class DimensionMDE(Dimension):
    binningChanged = Signal()
    """
    MDEventWorkspace has additional properties for either number_of_bins or thickness

    from mantidqt.widgets.sliceviewer.dimensionwidget import DimensionMDE
    from qtpy.QtWidgets import QApplication
    app = QApplication([])
    window = DimensionMDE({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'})
    window.show()
    app.exec_()
    """

    def __init__(self, dim_info, number=0, state=State.NONE, parent=None):

        # hack in a number_of_bins for MDEventWorkspace
        dim_info['number_of_bins'] = 1000
        dim_info['width'] = (dim_info['maximum'] - dim_info['minimum']) / 1000

        self.spinBins = QSpinBox()
        self.spinBins.setRange(2, 9999)
        self.spinBins.setValue(100)
        self.spinBins.hide()
        self.spinBins.setMinimumWidth(110)
        self.spinThick = QDoubleSpinBox()
        self.spinThick.setRange(0.001, 999)
        self.spinThick.setValue(0.1)
        self.spinThick.setSingleStep(0.1)
        self.spinThick.setDecimals(3)
        self.spinThick.setMinimumWidth(110)
        self.rebinLabel = QLabel("thick")
        self.rebinLabel.setMinimumWidth(44)

        super().__init__(dim_info, number, state, parent)

        self.spinBins.valueChanged.connect(self.binningChanged)
        self.spinThick.valueChanged.connect(self.valueChanged)

        self.layout.addWidget(self.spinBins)
        self.layout.addWidget(self.spinThick)
        self.layout.addWidget(self.rebinLabel)

    def get_bins(self):
        return int(self.spinBins.value())

    def get_thickness(self):
        return float(self.spinThick.value())

    def set_state(self, state):
        super().set_state(state)
        if self.state == State.X:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.Y:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.NONE:
            self.spinBins.hide()
            self.spinThick.show()
            self.rebinLabel.setText('thick')
        else:
            self.spinBins.hide()
            self.spinThick.hide()
            self.rebinLabel.hide()
Beispiel #7
0
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self._default_font_size = data['font_size']
        self._default_annotation_size = 18
        self._default_clipping_min = data['clipping_min']
        self._default_clipping_max = data['clipping_max']

        self.dim_max = data['dim_max']
        if USE_ANNOTATION_INT:
            self._default_annotation_size_int = data['annotation_size_int']
        else:
            self._default_annotation_size_float = data['annotation_size_float']

        #self.out_data = data
        self._picker_size = data['picker_size'] * 100.

        self.annotation_color_float, self.annotation_color_int = _check_color(
            data['annotation_color'])
        self.background_color_float, self.background_color_int = _check_color(
            data['background_color'])
        self.text_color_float, self.text_color_int = _check_color(
            data['text_color'])

        #self.setupUi(self)
        self.setWindowTitle('Preferences')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_set_font(self._default_font_size)
        #self.show()

    def create_widgets(self):
        """creates the display window"""
        # Text Size
        self.font_size = QLabel("Text Size:")
        self.font_size_edit = QSpinBox(self)
        self.font_size_edit.setValue(self._default_font_size)
        self.font_size_edit.setRange(7, 20)
        self.font_size_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # Annotation Color
        self.annotation_color = QLabel("Annotation Color:")
        self.annotation_color_edit = QPushButtonColor(
            self.annotation_color_int)

        # Background Color
        self.background_color = QLabel("Background Color:")
        self.background_color_edit = QPushButtonColor(
            self.background_color_int)

        # Text Color
        self.text_color = QLabel("Text Color:")
        self.text_color_edit = QPushButtonColor(self.text_color_int)

        #-----------------------------------------------------------------------
        # Annotation Size
        if USE_ANNOTATION_INT:
            self.annotation_size = QLabel("Annotation Size:")
            self.annotation_size_edit = QSpinBox(self)
            self.annotation_size_edit.setRange(1, 500)
            self.annotation_size_edit.setValue(
                self._default_annotation_size_int)
            self.annotation_size_button = QPushButton("Default")
        else:
            self.annotation_size = QLabel("Annotation Size:")
            self.annotation_size_edit = QDoubleSpinBox(self)
            self.annotation_size_edit.setRange(0.0, self.dim_max)

            log_dim = log10(self.dim_max)
            decimals = int(ceil(abs(log_dim)))
            decimals = max(6, decimals)
            self.annotation_size_edit.setDecimals(decimals)
            #self.annotation_size_edit.setSingleStep(self.dim_max / 100.)
            self.annotation_size_edit.setSingleStep(self.dim_max / 1000.)
            self.annotation_size_edit.setValue(
                self._default_annotation_size_float)

        #-----------------------------------------------------------------------
        # Picker Size
        self.picker_size = QLabel("Picker Size (% of Screen):")
        self.picker_size_edit = QDoubleSpinBox(self)
        self.picker_size_edit.setRange(0., 10.)

        log_dim = log10(self.dim_max)
        decimals = int(ceil(abs(log_dim)))

        decimals = max(6, decimals)
        self.picker_size_edit.setDecimals(decimals)
        self.picker_size_edit.setSingleStep(10. / 5000.)
        self.picker_size_edit.setValue(self._picker_size)

        #-----------------------------------------------------------------------
        # Clipping Min
        self.clipping_min = QLabel("Clipping Min:")
        self.clipping_min_edit = QLineEdit(str(self._default_clipping_min))
        self.clipping_min_button = QPushButton("Default")

        # Clipping Max
        self.clipping_max = QLabel("Clipping Max:")
        self.clipping_max_edit = QLineEdit(str(self._default_clipping_max))
        self.clipping_max_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # closing
        self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

    def create_layout(self):
        grid = QGridLayout()

        grid.addWidget(self.font_size, 0, 0)
        grid.addWidget(self.font_size_edit, 0, 1)
        grid.addWidget(self.font_size_button, 0, 2)

        grid.addWidget(self.background_color, 1, 0)
        grid.addWidget(self.background_color_edit, 1, 1)

        grid.addWidget(self.text_color, 2, 0)
        grid.addWidget(self.text_color_edit, 2, 1)

        grid.addWidget(self.annotation_color, 3, 0)
        grid.addWidget(self.annotation_color_edit, 3, 1)

        grid.addWidget(self.annotation_size, 4, 0)
        grid.addWidget(self.annotation_size_edit, 4, 1)
        if USE_ANNOTATION_INT:
            grid.addWidget(self.annotation_size_button, 4, 2)

        grid.addWidget(self.picker_size, 5, 0)
        grid.addWidget(self.picker_size_edit, 5, 1)

        #grid.addWidget(self.clipping_min, 6, 0)
        #grid.addWidget(self.clipping_min_edit, 6, 1)
        #grid.addWidget(self.clipping_min_button, 6, 2)

        #grid.addWidget(self.clipping_max, 7, 0)
        #grid.addWidget(self.clipping_max_edit, 7, 1)
        #grid.addWidget(self.clipping_max_button, 7, 2)

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)

        vbox.addStretch()
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        self.font_size_button.clicked.connect(self.on_default_font_size)
        self.font_size_edit.valueChanged.connect(self.on_set_font)

        if USE_ANNOTATION_INT:
            self.annotation_size_button.clicked.connect(
                self.on_default_annotation_size)
        self.annotation_size_edit.editingFinished.connect(
            self.on_set_annotation_size)
        self.annotation_size_edit.valueChanged.connect(
            self.on_set_annotation_size)
        self.annotation_color_edit.clicked.connect(self.on_annotation_color)

        self.background_color_edit.clicked.connect(self.on_background_color)
        self.text_color_edit.clicked.connect(self.on_text_color)

        self.picker_size_edit.valueChanged.connect(self.on_picker_size)
        self.picker_size_edit.editingFinished.connect(self.on_picker_size)
        self.picker_size_edit.valueChanged.connect(self.on_picker_size)

        self.clipping_min_button.clicked.connect(self.on_default_clipping_min)
        self.clipping_max_button.clicked.connect(self.on_default_clipping_max)

        self.apply_button.clicked.connect(self.on_apply)
        self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)
        # closeEvent

    def on_set_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)

    def on_set_annotation_size(self, value=None):
        """update the annotation size"""
        if value is None:
            value = float(self.annotation_size_edit.text())
        self._annotation_size = value
        #self.on_apply(force=True)
        #self.min_edit.setText(str(self._default_min))
        #self.min_edit.setStyleSheet("QLineEdit{background: white;}")
        self.update_annotation_size_color()

    def update_annotation_size_color(self):
        if self.win_parent is not None:
            self.win_parent.settings.set_annotation_size_color(
                self._annotation_size, self.annotation_color_float)

    def on_annotation_color(self):
        rgb_color_ints = self.annotation_color_int
        title = "Choose an annotation color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.annotation_color_edit, rgb_color_ints, title)
        if passed:
            self.annotation_color_int = rgb_color_ints
            self.annotation_color_float = rgb_color_floats
            self.update_annotation_size_color()

    def on_background_color(self):
        """ Choose a background color """
        rgb_color_ints = self.background_color_int
        title = "Choose a background color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.background_color_edit, rgb_color_ints, title)
        if passed:
            self.background_color_int = rgb_color_ints
            self.background_color_float = rgb_color_floats
            if self.win_parent is not None:
                self.win_parent.settings.set_background_color(rgb_color_floats)

    def on_text_color(self):
        """ Choose a text color """
        rgb_color_ints = self.text_color_int
        title = "Choose a text color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.text_color_edit, rgb_color_ints, title)
        if passed:
            self.text_color_int = rgb_color_ints
            self.text_color_float = rgb_color_floats
            if self.win_parent is not None:
                self.win_parent.settings.set_text_color(rgb_color_floats)

    def on_color(self, color_edit, rgb_color_ints, title):
        """pops a color dialog"""
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, title)
        if not col.isValid():
            return False, rgb_color_ints, None

        color_float = col.getRgbF()[:3]  # floats
        color_int = [int(colori * 255) for colori in color_float]

        assert isinstance(color_float[0], float), color_float
        assert isinstance(color_int[0], int), color_int

        color_edit.setStyleSheet("QPushButton {"
                                 "background-color: rgb(%s, %s, %s);" %
                                 tuple(color_int) +
                                 #"border:1px solid rgb(255, 170, 255); "
                                 "}")
        return True, color_int, color_float

    def on_picker_size(self):
        self._picker_size = float(self.picker_size_edit.text())
        if self.win_parent is not None:
            self.win_parent.element_picker_size = self._picker_size / 100.
        #self.on_apply(force=True)

    def on_default_font_size(self):
        self.font_size_edit.setValue(self._default_font_size)
        self.on_set_font(self._default_font_size)

    def on_default_annotation_size(self):
        self.annotation_size_edit.setValue(self._default_annotation_size)
        self.on_set_annotation_size(self._default_annotation_size)

    def on_default_clipping_min(self):
        self.clipping_min_edit.setText(str(self._default_clipping_min))
        self.clipping_min_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_clipping_max(self):
        self.clipping_max_edit.setText(str(self._default_clipping_max))
        self.clipping_max_edit.setStyleSheet("QLineEdit{background: white;}")

    @staticmethod
    def check_float(cell):
        text = cell.text()
        value = float(text)
        return value, True

    @staticmethod
    def check_label_float(cell):
        text = cell.text()
        try:
            value = eval_float_from_string(text)
            cell.setStyleSheet("QLineEdit{background: white;}")
            return value, True
        except ValueError:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    def on_validate(self):
        font_size_value, flag0 = self.check_float(self.font_size_edit)
        annotation_size_value, flag1 = self.check_float(
            self.annotation_size_edit)
        assert isinstance(self.annotation_color_float[0],
                          float), self.annotation_color_float
        assert isinstance(self.annotation_color_int[0],
                          int), self.annotation_color_int
        picker_size_value, flag2 = self.check_float(self.picker_size_edit)

        clipping_min_value, flag3 = self.check_label_float(
            self.clipping_min_edit)
        clipping_max_value, flag4 = self.check_label_float(
            self.clipping_max_edit)

        if all([flag0, flag1, flag2, flag3, flag4]):
            self._annotation_size = annotation_size_value
            self._picker_size = picker_size_value

            self.out_data['font_size'] = int(font_size_value)
            self.out_data['clipping_min'] = min(clipping_min_value,
                                                clipping_max_value)
            self.out_data['clipping_max'] = max(clipping_min_value,
                                                clipping_max_value)
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self, force=False):
        passed = self.on_validate()
        if (passed or force) and self.win_parent is not None:
            self.win_parent.settings.on_set_font_size(
                self.out_data['font_size'])

            #self.win_parent.settings.set_annotation_size_color(
            #self._annotation_size, self.annotation_color_float)
            #self.win_parent.element_picker_size = self._picker_size / 100.
        if passed and self.win_parent is not None:
            self.win_parent._apply_clipping(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
Beispiel #8
0
class SliderSpinBox(QWidget):
    valueChanged = Signal(float)

    def __init__(self, parent=None, value_range=(0, 100), slider_steps=100, spinbox_steps=1000, decimals=None):
        QWidget.__init__(self, parent)
        layout = QHBoxLayout(self)
        self.setLayout(layout)
        self.horizontalSlider = QSlider(Qt.Horizontal, self)
        self.doubleSpinBox = QDoubleSpinBox(self)
        self.decimals = decimals
        layout.setMargin(0)
        layout.addWidget(self.doubleSpinBox)
        layout.addWidget(self.horizontalSlider)

        self.doubleSpinBox.valueChanged.connect(self.spinbox_changed)
        self.horizontalSlider.valueChanged.connect(self.slider_changed)

        self.wt = []
        self.changer = None
        self.slider_steps = slider_steps
        self.horizontalSlider.setMaximum(slider_steps)
        self.spinbox_steps = spinbox_steps
        self.set_range(value_range)

    def set_value(self, value):
        self.doubleSpinBox.setValue(value)

    value = property(lambda self: self.doubleSpinBox.value(), set_value)

    def set_range(self, value_range):
        self.changer = "set_range"
        spinbox_step_decimal = np.ceil(np.log10(1. / (float(value_range[1] - value_range[0]) / self.spinbox_steps)))
        self.slider_decimals = int(np.ceil(np.log10(self.slider_steps) - np.log10(value_range[1] - value_range[0])))
        if self.decimals is None:
            self.doubleSpinBox.setDecimals(spinbox_step_decimal + 1)
        else:
            self.doubleSpinBox.setDecimals(self.decimals)
            spinbox_step_decimal = min(self.decimals, spinbox_step_decimal)
            self.slider_decimals = min(self.decimals, self.slider_decimals)
        self.doubleSpinBox.setSingleStep(10 ** -spinbox_step_decimal)


        self.value_range = value_range
        self.doubleSpinBox.setMinimum(value_range[0])
        self.doubleSpinBox.setMaximum(value_range[1])

        self.horizontalSlider.setValue(np.floor(value_range[0]))
        self.changer = None
        self.doubleSpinBox.setValue(value_range[0])

    def range(self):
        return self.doubleSpinBox.minimum(), self.doubleSpinBox.maximum()

    def slider_changed(self, value):
        if self.changer is None:
            self.changer = 'slider'
            value = np.round(value * (self.value_range[1] - self.value_range[0]) / self.slider_steps + self.value_range[0], self.slider_decimals)

            self.doubleSpinBox.setValue(value)
            self.changer = None
            self.value_changed(value)

    def spinbox_changed(self, value):
        if self.changer is None:
            self.changer = 'spinbox'

            slider_value = .5 + (value - self.value_range[0]) * self.slider_steps / (self.value_range[1] - self.value_range[0])
            self.horizontalSlider.setValue(slider_value)
            self.changer = None
            self.value_changed(value)

    @postpone_until_last_call_finishes
    def value_changed(self, value):
        self.valueChanged.emit(value)
Beispiel #9
0
class AnimationWindow(PyDialog):
    """
    +-------------------+
    | Animation         |
    +-------------------------+
    | icase   ______          |
    | scale   ______  Default |
    | time    ______  Default |
    |                         |
    | nframes ______  Default |
    | resolu. ______  Default |
    | Dir     ______  Browse  |
    | iFrame  ______          |
    |                         |
    | Animations:             |
    | o Scale, Phase, Time    |
    |                         |
    | x delete images         |
    | x repeat                |  # TODO: change to an integer
    | x make gif              |
    |                         |
    |      Step, RunAll       |
    |         Close           |
    +-------------------------+

    TODO: add key-frame support
    """
    def __init__(self, data, win_parent=None, fringe_cases=None, is_gui_parent=False):
        PyDialog.__init__(self, data, win_parent)

        # is the parent the gui?
        self.is_gui_parent = False
        self.fringe_cases = fringe_cases
        self.set_font_size(data['font_size'])
        self.istep = 0
        self._animate_type = 'time'

        self._updated_animation = False
        self._active_deformation = 0.
        self._icase_fringe = data['icase_fringe']
        self._icase_disp = data['icase_disp']
        self._icase_vector = data['icase_vector']

        self._default_title = data['title']
        self._default_time = data['time']
        self._default_fps = data['frames/sec']
        self._default_resolution = data['resolution']

        self._scale = data['scale']
        self._default_scale = data['default_scale']
        self._default_is_scale = data['is_scale']

        self._arrow_scale = data['arrow_scale']
        self._default_arrow_scale = data['default_arrow_scale']

        self._phase = data['phase']
        self._default_phase = data['default_phase']

        self._default_dirname = data['dirname']
        self._default_gif_name = os.path.join(self._default_dirname, data['title'] + '.gif')

        self.animation_types = [
            'Animate Scale',
        ]
            #'Animate Phase',
            #'Animate Time',
            #'Animate Frequency Sweep'
        #]

        self.setWindowTitle('Animate Model')
        self.create_widgets()
        self.create_layout()
        self.set_connections()

        self.is_gui = False
        self.gui = None
        if hasattr(self.win_parent, '_updated_legend'):
            self.win_parent.is_animate_open = True
            self.is_gui = True
            self.gui = self.win_parent.win_parent

        if is_gui_parent:
            self.is_gui = True
            self.gui = self.win_parent
        self.on_update_min_max_defaults()


    def create_widgets(self):
        """creates the menu objects"""
        self.box_scale = QGroupBox('Animate Scale')
        self.box_time = QGroupBox('Animate Time')

        icase_max = 1000  # TODO: update 1000

        self.checkbox_fringe = QCheckBox('Animate')
        self.checkbox_fringe.setToolTip(
            'Animate the fringe in addition to the deflection')
        #self.checkbox_disp = QCheckBox('Animate')
        self.checkbox_fringe.setEnabled(False)

        self.icase_fringe_label = QLabel("iCase (Fringe):")
        self.icase_fringe_edit = QSpinBox(self)
        self.icase_fringe_edit.setRange(0, icase_max)
        self.icase_fringe_edit.setSingleStep(1)
        if self._icase_fringe is not None:
            self.icase_fringe_edit.setValue(self._icase_fringe)
        self.icase_fringe_edit.setToolTip(
            'Case Number for the Scale/Phase Animation Type.\n'
            'Defaults to the result you had shown when you clicked "Create Animation".\n'
            'iCase can be seen by clicking "Apply" on a result.')

        self.icase_disp_label = QLabel("iCase (Disp):")
        self.icase_disp_edit = QSpinBox(self)
        self.icase_disp_edit.setRange(1, icase_max)
        self.icase_disp_edit.setSingleStep(1)
        if self._icase_disp is not None:
            self.icase_disp_edit.setValue(self._icase_disp)

        self.checkbox_vector = QCheckBox('Animate')
        self.checkbox_vector.setToolTip(
            'Animate the vector in addition to the deflection')
        self.checkbox_vector.hide()
        #self.checkbox_disp = QCheckBox('Animate')

        self.icase_vector_label = QLabel("iCase (Vector):")
        self.icase_vector_edit = QSpinBox(self)
        self.icase_vector_edit.setRange(1, icase_max)
        self.icase_vector_edit.setSingleStep(1)
        if self._icase_vector is not None:
            self.icase_vector_edit.setValue(self._icase_vector)

        self.scale_label = QLabel("True Scale:")
        self.scale_edit = QLineEdit(str(self._scale))
        self.scale_button = QPushButton("Default")
        self.scale_edit.setToolTip('Scale factor of the "deflection"')
        self.scale_button.setToolTip('Sets the scale factor of the gif to %s' % self._scale)

        self.arrow_scale_label = QLabel("Arrow Scale:")
        self.arrow_scale_edit = QLineEdit(str(self._scale))
        self.arrow_scale_button = QPushButton("Default")
        self.arrow_scale_edit.setToolTip('Scale factor of the "arrows"')
        self.arrow_scale_button.setToolTip('Sets the arrow scale factor of the gif to %s' % (
            self._arrow_scale))

        self.arrow_scale_label.setVisible(False)
        self.arrow_scale_edit.setVisible(False)
        self.arrow_scale_button.setVisible(False)

        self.time_label = QLabel("Total Time (sec):")
        self.time_edit = QDoubleSpinBox(self)
        self.time_edit.setValue(self._default_time)
        self.time_edit.setRange(0.1, 5. * 60.)
        self.time_edit.setDecimals(2)
        self.time_edit.setSingleStep(0.1)
        self.time_button = QPushButton("Default")
        self.time_edit.setToolTip("Total time of the gif")
        self.time_button.setToolTip('Sets the total time of the gif to %.2f' % self._default_time)

        self.fps_label = QLabel("Frames/Second:")
        self.fps_edit = QSpinBox(self)
        self.fps_edit.setRange(1, 60)
        self.fps_edit.setSingleStep(1)
        self.fps_edit.setValue(self._default_fps)
        self.fps_button = QPushButton("Default")
        self.fps_edit.setToolTip("A higher FPS is smoother, but may not play well for large gifs")
        self.fps_button.setToolTip('Sets the FPS to %s' % self._default_fps)

        self.resolution_label = QLabel("Resolution Scale:")
        self.resolution_edit = QSpinBox(self)
        self.resolution_edit.setRange(1, 5)
        self.resolution_edit.setSingleStep(1)
        self.resolution_edit.setValue(self._default_resolution)
        self.resolution_button = QPushButton("Default")
        self.resolution_edit.setToolTip('Scales the window resolution by an integer factor')
        self.resolution_button.setToolTip('Sets the resolution to %s' % self._default_resolution)

        #-----------------
        # Time plot
        self.fringe_label = QLabel("Fringe")

        self.icase_fringe_start_edit = QSpinBox(self)
        self.icase_fringe_start_edit.setRange(0, icase_max)
        self.icase_fringe_start_edit.setSingleStep(1)
        self.icase_fringe_start_edit.setValue(self._icase_fringe)
        self.icase_fringe_start_button = QPushButton("Default")

        self.icase_fringe_end_edit = QSpinBox(self)
        self.icase_fringe_end_edit.setRange(0, icase_max)
        self.icase_fringe_end_edit.setSingleStep(1)
        self.icase_fringe_end_edit.setValue(self._icase_fringe)
        self.icase_fringe_end_button = QPushButton("Default")

        self.icase_fringe_delta_edit = QSpinBox(self)
        self.icase_fringe_delta_edit.setRange(1, icase_max)
        self.icase_fringe_delta_edit.setSingleStep(1)
        self.icase_fringe_delta_edit.setValue(1)
        self.icase_fringe_delta_button = QPushButton("Default")

        self.displacement_label = QLabel("Displacement")
        self.icase_start = QLabel("iCase Start:")
        self.icase_disp_start_edit = QSpinBox(self)
        self.icase_disp_start_edit.setRange(0, icase_max)
        self.icase_disp_start_edit.setSingleStep(1)
        self.icase_disp_start_edit.setValue(self._icase_fringe)
        self.icase_disp_start_button = QPushButton("Default")

        self.icase_end_label = QLabel("iCase End:")
        self.icase_disp_end_edit = QSpinBox(self)
        self.icase_disp_end_edit.setRange(0, icase_max)
        self.icase_disp_end_edit.setSingleStep(1)
        self.icase_disp_end_edit.setValue(self._icase_fringe)
        self.icase_disp_end_button = QPushButton("Default")

        self.icase_delta_label = QLabel("iCase Delta:")
        self.icase_disp_delta_edit = QSpinBox(self)
        self.icase_disp_delta_edit.setRange(1, icase_max)
        self.icase_disp_delta_edit.setSingleStep(1)
        self.icase_disp_delta_edit.setValue(1)
        self.icase_disp_delta_button = QPushButton("Default")

        self.min_value_enable = QCheckBox()
        self.min_value_label = QLabel("Min Value:")
        self.min_value_edit = QLineEdit('')
        #self.min_value_edit.setRange(1, 1000)
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.min_value_button = QPushButton("Default")

        self.max_value_enable = QCheckBox()
        self.max_value_label = QLabel("Max Value:")
        self.max_value_edit = QLineEdit('')
        #self.min_value_edit.setRange(1, 1000)  # TODO: update 1000
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.max_value_button = QPushButton("Default")

        # TODO: enable this (uncomment) ------------------------------------------
        #self.min_value_enable.hide()
        #self.min_value.hide()
        #self.min_value_edit.hide()
        #self.min_value_button.hide()

        #self.max_value_enable.hide()
        #self.max_value.hide()
        #self.max_value_edit.hide()
        #self.max_value_button.hide()
        # TODO: enable this (uncomment) ------------------------------------------

        self.icase_disp_start_edit.setToolTip('The first frame of the animation')
        self.icase_disp_end_edit.setToolTip(
            'The last frame of the animation\n'
            'Assumes icase_start + nframes * icase_delta = icase_end')
        self.icase_disp_delta_edit.setToolTip(
            'The frame step size (to skip non-consecutive results).\n'
            'Frame skipping can be used to:\n'
            "  - skip across results that you don't want to plot\n"
            '  - adjust the FPS')

        self.min_value_edit.setToolTip('Min value of the legend (not supported)')
        self.max_value_edit.setToolTip('Max value of the legend (not supported)')
        #'time' : 0.,
        #'default_time' : 0,
        #'icase_start' : 10,
        #'icase_delta' : 3,
        #'min_value' : 0.,
        #'max_value' : 1000.,

        self.browse_folder_label = QLabel('Output Directory:')
        self.browse_folder_edit = QLineEdit(str(self._default_dirname))
        self.browse_folder_button = QPushButton('Browse...')
        self.browse_folder_edit.setToolTip('Location to save the png/gif files')

        self.gif_label = QLabel("Gif Filename:")
        self.gif_edit = QLineEdit(str(self._default_title + '.gif'))
        self.gif_button = QPushButton('Default')
        self.gif_edit.setToolTip('Name of the gif')
        self.gif_button.setToolTip('Sets the name of the gif to %s.gif' % self._default_title)

        # scale / phase
        if 1: # pragma: no cover
            self.animate_scale_radio = QRadioButton("Animate Scale")
            self.animate_phase_radio = QRadioButton("Animate Phase")
            self.animate_time_radio = QRadioButton("Animate Time")
            self.animate_freq_sweeep_radio = QRadioButton("Animate Frequency Sweep")
            self.animate_scale_radio.setToolTip(
                'Animates the scale factor based on the "Animation Type"')
            self.animate_time_radio.setToolTip('Animates the time/load/mode step')

            self.animate_scale_radio.setChecked(self._default_is_scale)
            self.animate_phase_radio.setChecked(not self._default_is_scale)
            self.animate_time_radio.setChecked(False)

            msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n'
            if self._default_phase is None:
                self.animate_phase_radio.setDisabled(True)
                self.animate_phase_radio.setToolTip('Animates the phase angle '
                                                    '(only for complex results)')
                msg += 'Phase : Animates the phase angle (only for complex results)\n'
            else:
                self.animate_phase_radio.setToolTip("Animates the phase angle")
                msg += 'Phase : Animates the phase angle\n'
            msg += (
                'Time : Animates the time/load/mode step\n'
                'Freq Sweep : Animates a complex result across a range of frequencies '
                '(not supported)\n'
            )

            self.animate_freq_sweeep_radio.setDisabled(True)
            self.animate_freq_sweeep_radio.setToolTip(
                'Animates a complex result across a range of frequencies (not supported)')
        else:
            msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n'
            if self._default_phase is None:
                #self.animate_phase_radio.setDisabled(True)
                #self.animate_phase_radio.setToolTip('Animates the phase angle '
                                                    #'(only for complex results)')
                msg += 'Phase : Animates the phase angle (only for complex results)\n'
            else:
                #self.animate_phase_radio.setToolTip("Animates the phase angle")
                msg += 'Phase : Animates the phase angle\n'
            msg += (
                'Time : Animates the time/load/mode step\n'
                'Freq Sweep : Animates a complex result across a range of frequencies '
                '(not supported)\n'
            )

        self.animation_type = QLabel("Animation Type:")
        animation_type = OrderedDict()
        #scale_msg = 'Scale\n'
        #phase_msg = 'Phase\n'
        #time_msg = 'Time\n'
        #animation_types = [
            #('Animate Scale', scale_msg),
            #('Animate Phase', phase_msg),
            #('Animate Time', time_msg),
            ##'Animate Frequency Sweep'
        #]

        if self._phase is not None:
            self.animation_types.append('Animate Phase')
        self.animation_types.append('Animate Time')

        self.animation_profile_label = QLabel("Animation Profile:")

        self.animation_profile_edit = QComboBox()
        for animation_profile in ANIMATION_PROFILES:
            self.animation_profile_edit.addItem(animation_profile)
        self.animation_profile_edit.setToolTip('The profile for a scaled GIF')

        self.animation_type_edit = QComboBox()
        # TODO: add a tooltip for each item
        for animation_type in self.animation_types:
            self.animation_type_edit.addItem(animation_type)
        #self.animation_type_edit.setToolTip('The profile for a scaled GIF')
        self.animation_type_edit.setToolTip(msg.rstrip())

        self.csv_profile_label = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_browse_button = QPushButton('Browse')
        self.csv_profile_edit.setToolTip(
            'The path to the CSV file of (Scale1, Scale2, Scale3, ...)')

        #widget = QWidget(self)
        #horizontal_vertical_group = QButtonGroup(widget)
        #horizontal_vertical_group.addButton(self.animate_scale_radio)
        #horizontal_vertical_group.addButton(self.animate_phase_radio)
        #horizontal_vertical_group.addButton(self.animate_time_radio)
        #horizontal_vertical_group.addButton(self.animate_freq_sweeep_radio)

        # animate in gui
        self.animate_in_gui_checkbox = QCheckBox("Animate In GUI?")
        self.animate_in_gui_checkbox.setChecked(True)

        # make images
        self.make_images_checkbox = QCheckBox("Make images?")
        self.make_images_checkbox.setChecked(True)

        # make images
        self.overwrite_images_checkbox = QCheckBox("Overwrite images?")
        self.overwrite_images_checkbox.setChecked(True)

        # delete images when finished
        self.delete_images_checkbox = QCheckBox("Delete images when finished?")
        self.delete_images_checkbox.setChecked(True)

        # endless loop
        self.repeat_checkbox = QCheckBox("Repeat?")
        self.repeat_checkbox.setChecked(True)
        self.repeat_checkbox.setToolTip("Repeating creates an infinitely looping gif")

        # endless loop
        self.make_gif_checkbox = QCheckBox("Make Gif?")
        if IS_IMAGEIO:
            self.make_gif_checkbox.setChecked(True)
        else:
            self.make_gif_checkbox.setChecked(False)
            self.make_gif_checkbox.setEnabled(False)
            self.make_gif_checkbox.setToolTip('imageio is not available; install it')

        # bottom buttons
        self.step_button = QPushButton("Step")
        self.wipe_button = QPushButton("Wipe Deformed Shape")
        self.stop_button = QPushButton("Stop")
        self.run_button = QPushButton("Run")

        self.step_button.setToolTip('Steps through the animation (for testing)')
        self.wipe_button.setToolTip('Removes the existing "deflecton" from the animation')
        self.stop_button.setToolTip('Stops the animation')
        self.run_button.setToolTip('Creates the animation')
        self.step_button.hide()
        self.wipe_button.hide()

        self.wipe_button.setEnabled(False)
        #self.wipe_button.hide()
        self.stop_button.setEnabled(False)

        self.cancel_button = QPushButton("Close")

        #self.set_grid_time(enabled=False)
        #self.set_grid_scale(enabled=self._default_is_scale)
        if self._default_phase:
            self.on_animate_phase(force=True)
            set_combo_box_text(self.animation_type_edit, 'Animate Phase')
        else:
            self.on_animate_scale(force=True)

    def set_connections(self):
        """creates the actions for the menu"""
        self.checkbox_vector.clicked.connect(self.on_checkbox_vector)

        self.scale_button.clicked.connect(self.on_default_scale)
        self.arrow_scale_button.clicked.connect(self.on_default_arrow_scale)
        self.time_button.clicked.connect(self.on_default_time)

        self.fps_button.clicked.connect(self.on_default_fps)
        self.resolution_button.clicked.connect(self.on_default_resolution)
        self.browse_folder_button.clicked.connect(self.on_browse_folder)
        self.csv_profile_browse_button.clicked.connect(self.on_browse_csv)
        self.gif_button.clicked.connect(self.on_default_title)

        self.step_button.clicked.connect(self.on_step)
        self.wipe_button.clicked.connect(self.on_wipe)
        self.stop_button.clicked.connect(self.on_stop)
        self.run_button.clicked.connect(self.on_run)
        self.min_value_enable.clicked.connect(self.on_min_value_enable)
        self.max_value_enable.clicked.connect(self.on_max_value_enable)

        self.min_value_button.clicked.connect(self.on_min_value_default)
        self.max_value_button.clicked.connect(self.on_max_value_default)
        self.icase_disp_start_button.clicked.connect(self.on_update_min_max_defaults)

        #self.animate_scale_radio.clicked.connect(self.on_animate_scale)
        #self.animate_phase_radio.clicked.connect(self.on_animate_phase)
        #self.animate_time_radio.clicked.connect(self.on_animate_time)
        self.animation_type_edit.currentIndexChanged.connect(self.on_animate)
        #self.animate_freq_sweeep_radio

        self.cancel_button.clicked.connect(self.on_cancel)

        self.animate_in_gui_checkbox.clicked.connect(self.on_animate_in_gui)
        self.animate_in_gui_checkbox.setChecked(True)
        self.on_animate_in_gui()

    def on_checkbox_vector(self):
        is_enabled = self.checkbox_vector.isEnabled()
        is_checked = self.checkbox_vector.isChecked()
        enable_edit = is_enabled and is_checked
        self.icase_vector_label.setEnabled(is_checked)
        self.icase_vector_edit.setEnabled(enable_edit)

    def on_animate_in_gui(self):
        animate_in_gui = self.animate_in_gui_checkbox.isChecked()
        enable = not animate_in_gui
        if HIDE_WHEN_INACTIVE:
            self.make_images_checkbox.setVisible(enable)
            self.delete_images_checkbox.setVisible(enable)
            self.make_gif_checkbox.setVisible(enable)
            self.repeat_checkbox.setVisible(enable)
            self.resolution_button.setVisible(enable)
            self.resolution_label.setVisible(enable)
            self.resolution_edit.setVisible(enable)
            self.gif_label.setVisible(enable)
            self.gif_edit.setVisible(enable)
            self.gif_button.setVisible(enable)
            self.browse_folder_label.setVisible(enable)
            self.browse_folder_button.setVisible(enable)
            self.browse_folder_edit.setVisible(enable)
            self.step_button.setEnabled(enable)

        self.make_images_checkbox.setEnabled(enable)
        self.delete_images_checkbox.setEnabled(enable)
        self.make_gif_checkbox.setEnabled(enable)
        self.repeat_checkbox.setEnabled(enable)
        self.resolution_button.setEnabled(enable)
        self.resolution_edit.setEnabled(enable)
        self.gif_edit.setEnabled(enable)
        self.gif_button.setEnabled(enable)
        self.browse_folder_button.setEnabled(enable)
        self.browse_folder_edit.setEnabled(enable)
        self.step_button.setEnabled(enable)
        #wipe_button

    def on_animate(self, value):
        """
        animate pulldown

        Parameters
        ----------
        value : int
            index in animation_types
        """
        #animation_types = ['Animate Scale', 'Animate Phase', 'Animate Time',
                           #'Animate Frequency Sweep']
        animation_type = self.animation_types[value]
        if animation_type == 'Animate Scale':
            self.on_animate_scale()
        elif animation_type == 'Animate Phase':
            self.on_animate_phase()
        elif animation_type == 'Animate Time':
            self.on_animate_time()
        else:
            raise NotImplementedError('value = ', value)

    def on_animate_time(self, force=False):
        """enables the secondary input"""
        #print('on_animate_time')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'time')
        self.set_grid_time(True, 'time')
        self._animate_type = 'time'

    def on_animate_scale(self, force=False):
        """enables the secondary input"""
        #print('on_animate_scale')
        self.set_grid_scale(True, 'scale')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'scale')
        self._animate_type = 'scale'

    def on_animate_phase(self, force=False):
        """enables the secondary input"""
        #print('on_animate_phase')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'phase')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'phase')
        self._animate_type = 'phase'

    def set_grid_scale(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_scale; enabled = %r' % (word, enabled))
        if HIDE_WHEN_INACTIVE:
            self.box_scale.setVisible(enabled)
            self.animation_profile_label.setVisible(enabled)
            self.animation_profile_edit.setVisible(enabled)
            #self.min_value_enable.setVisible(enabled)
            #self.max_value_enable.setVisible(enabled)

        self.animation_profile_label.setEnabled(enabled)
        self.animation_profile_edit.setEnabled(enabled)

        # TODO: doesn't work...
        #self.csv_profile.setEnabled(enabled)
        #self.csv_profile_edit.setEnabled(enabled)
        #self.csv_profile_button.setEnabled(enabled)

        self.min_value_enable.setEnabled(enabled)
        self.max_value_enable.setEnabled(enabled)
        self.on_min_value_enable()
        self.on_max_value_enable()


    def set_grid_time(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_time; enabled = %r' % (word, enabled))
        if HIDE_WHEN_INACTIVE:
            self.box_time.setVisible(enabled)
            self.checkbox_fringe.setVisible(not enabled)
            self.icase_fringe_label.setVisible(not enabled)
            self.icase_fringe_edit.setVisible(not enabled)
            self.icase_disp_label.setVisible(not enabled)
            self.icase_disp_edit.setVisible(not enabled)
            self.icase_vector_label.setVisible(not enabled)
            self.icase_vector_edit.setVisible(not enabled)

            #self.icase_fringe_delta_edit.setVisible(enabled)
            self.icase_disp_delta_edit.setVisible(enabled)
            self.icase_disp_delta_edit.setVisible(enabled)
            self.fps_label.setVisible(enabled)
            self.fps_edit.setVisible(enabled)
            self.fps_button.setVisible(enabled)

        self.displacement_label.setEnabled(enabled)
        self.fringe_label.setEnabled(enabled)

        self.icase_start.setEnabled(enabled)
        self.icase_disp_start_edit.setEnabled(enabled)
        self.icase_disp_start_button.setEnabled(enabled)
        self.icase_fringe_start_edit.setEnabled(enabled)
        self.icase_fringe_start_button.setEnabled(enabled)

        self.icase_end_label.setEnabled(enabled)
        self.icase_disp_end_edit.setEnabled(enabled)
        self.icase_disp_end_button.setEnabled(enabled)
        self.icase_fringe_end_edit.setEnabled(enabled)
        self.icase_fringe_end_button.setEnabled(enabled)

        self.icase_delta_label.setEnabled(enabled)
        self.icase_disp_delta_edit.setEnabled(enabled)
        self.icase_disp_delta_button.setEnabled(enabled)
        self.icase_fringe_delta_edit.setEnabled(enabled)
        self.icase_fringe_delta_button.setEnabled(enabled)

        #-----------------------------------------------------------------------
        is_min_enabled = self.min_value_enable.isChecked()
        self.min_value_label.setEnabled(is_min_enabled)
        self.min_value_edit.setEnabled(is_min_enabled)
        self.min_value_button.setEnabled(is_min_enabled)

        is_max_enabled = self.max_value_enable.isChecked()
        self.max_value_label.setEnabled(is_max_enabled)
        self.max_value_edit.setEnabled(is_max_enabled)
        self.max_value_button.setEnabled(is_max_enabled)

        self.min_value_enable.setEnabled(enabled)
        self.on_min_value_enable()
        #self.min_value.setEnabled(enabled)
        #self.min_value_edit.setEnabled(enabled)
        #self.min_value_button.setEnabled(enabled)

        self.max_value_enable.setEnabled(enabled)
        self.on_max_value_enable()
        #self.max_value.setEnabled(enabled)
        #self.max_value_edit.setEnabled(enabled)
        #self.max_value_button.setEnabled(enabled)

        self.icase_fringe_label.setEnabled(not enabled)
        self.icase_fringe_edit.setEnabled(not enabled)
        self.checkbox_fringe.setEnabled(not enabled)

        self.icase_disp_label.setEnabled(not enabled)
        self.icase_disp_edit.setEnabled(not enabled)

        self.icase_vector_label.setEnabled(not enabled)
        self.icase_vector_edit.setEnabled(not enabled)
        self.checkbox_vector.setEnabled(not enabled)
        self.on_checkbox_vector()

        self.fps_label.setEnabled(not enabled)
        self.fps_edit.setEnabled(not enabled)
        self.fps_button.setEnabled(not enabled)

    def on_min_value_enable(self):
        """
        The min edit value box is enabled when we switch to time
        and the box is checked
        """
        is_min_enabled = self.min_value_enable.isChecked() and self.min_value_enable.isEnabled()
        self.min_value_label.setEnabled(is_min_enabled)
        self.min_value_edit.setEnabled(is_min_enabled)
        self.min_value_button.setEnabled(is_min_enabled)

    def on_max_value_enable(self):
        """
        The max edit value box is enabled when we switch to time
        and the box is checked
        """
        is_max_enabled = self.max_value_enable.isChecked() and self.max_value_enable.isEnabled()
        self.max_value_label.setEnabled(is_max_enabled)
        self.max_value_edit.setEnabled(is_max_enabled)
        self.max_value_button.setEnabled(is_max_enabled)

    def on_update_min_max_defaults(self):
        """
        When the icase is changed, the min/max value default message is changed
        """
        icase = self.icase_disp_start_edit.value()
        min_value, max_value = self.get_min_max(icase)
        self.min_value_button.setToolTip('Sets the min value to %g' % min_value)
        self.max_value_button.setToolTip('Sets the max value to %g' % max_value)

    def on_min_value_default(self):
        """When min default icase is pressued, update the value"""
        icase = self.icase_disp_start_edit.value()
        min_value = self.get_min_max(icase)[0]
        self.min_value_edit.setText(str(min_value))
        self.min_value_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_max_value_default(self):
        """When max default icase is pressued, update the value"""
        icase = self.icase_disp_start_edit.value()
        max_value = self.get_min_max(icase)[1]
        self.max_value_edit.setText(str(max_value))
        self.max_value_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_browse_folder(self):
        """opens a folder dialog"""
        dirname = getexistingdirectory(parent=self, caption='Select a Directory',
                                       basedir='',
                                       options=QFileDialog.ShowDirsOnly)
        if not dirname:
            return
        self.browse_folder_edit.setText(dirname)

    def on_browse_csv(self):
        """opens a file dialog"""
        default_filename = ''
        file_types = 'Delimited Text (*.txt; *.dat; *.csv)'
        dirname = open_file_dialog(self, 'Select a CSV File', default_filename, file_types)
        if not dirname:
            return
        self.csv_profile_browse_button.setText(dirname)

    def on_default_title(self):
        """sets the default gif name"""
        self.gif_edit.setText(self._default_title + '.gif')

    def on_default_scale(self):
        """sets the default displacement scale factor"""
        if self.is_gui:
            icase_disp = self.icase_disp_edit.value()
            out = self.gui.legend_obj.get_legend_disp(
                icase_disp)
            unused_scale, unused_phase, default_scale, unused_default_phase = out
        else:
            default_scale = self._default_scale
        self.scale_edit.setText(str(default_scale))
        self.scale_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_arrow_scale(self):
        """sets the default arrow scale factor"""
        if self.is_gui:
            icase_vector = self.icase_vector_edit.value()
            out = self.gui.legend_obj.get_legend_vector(icase_vector)
            unused_arrow_scale, default_arrow_scale = out
        else:
            default_arrow_scale = self._default_arrow_scale
        self.arrow_scale_edit.setText(str(default_arrow_scale))
        self.arrow_scale_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_time(self):
        """sets the default gif time"""
        self.time_edit.setValue(self._default_time)

    def on_default_fps(self):
        """sets the default FPS"""
        self.fps_edit.setValue(self._default_fps)

    def on_default_resolution(self):
        """sets the default image resolution scale factor"""
        self.resolution_edit.setValue(self._default_resolution)

    def create_layout(self):
        """displays the menu objects"""
        grid = QGridLayout()
        irow = 0
        grid.addWidget(self.icase_fringe_label, irow, 0)
        grid.addWidget(self.icase_fringe_edit, irow, 1)
        grid.addWidget(self.checkbox_fringe, irow, 2)
        irow += 1

        grid.addWidget(self.icase_disp_label, irow, 0)
        grid.addWidget(self.icase_disp_edit, irow, 1)
        #grid.addWidget(self.checkbox_disp, irow, 2)
        irow += 1

        grid.addWidget(self.icase_vector_label, irow, 0)
        grid.addWidget(self.icase_vector_edit, irow, 1)
        grid.addWidget(self.checkbox_vector, irow, 2)
        irow += 1

        grid.addWidget(self.scale_label, irow, 0)
        grid.addWidget(self.scale_edit, irow, 1)
        grid.addWidget(self.scale_button, irow, 2)
        irow += 1

        grid.addWidget(self.arrow_scale_label, irow, 0)
        grid.addWidget(self.arrow_scale_edit, irow, 1)
        grid.addWidget(self.arrow_scale_button, irow, 2)
        irow += 1

        grid.addWidget(self.time_label, irow, 0)
        grid.addWidget(self.time_edit, irow, 1)
        grid.addWidget(self.time_button, irow, 2)
        irow += 1

        # spacer
        spacer = QLabel('')

        grid.addWidget(self.fps_label, irow, 0)
        grid.addWidget(self.fps_edit, irow, 1)
        grid.addWidget(self.fps_button, irow, 2)
        irow += 1


        grid.addWidget(self.animation_type, irow, 0)
        grid.addWidget(self.animation_type_edit, irow, 1)
        irow += 1

        grid.addWidget(spacer, irow, 0)
        irow += 1

        #----------
        #Time
        grid_time = QGridLayout()
        jrow = 0

        self.fringe_label.setAlignment(Qt.AlignCenter)
        self.displacement_label.setAlignment(Qt.AlignCenter)

        if not IS_TIME_FRINGE:
            self.fringe_label.hide()
            self.icase_fringe_delta_edit.hide()
            self.icase_fringe_start_edit.hide()
            self.icase_fringe_end_edit.hide()
            self.icase_fringe_delta_button.hide()

        grid_time.addWidget(self.displacement_label, jrow, 1)
        grid_time.addWidget(self.fringe_label, jrow, 2)
        jrow += 1

        grid_time.addWidget(self.icase_start, jrow, 0)
        grid_time.addWidget(self.icase_disp_start_edit, jrow, 1)
        grid_time.addWidget(self.icase_fringe_start_edit, jrow, 2)
        #grid_time.addWidget(self.icase_disp_start_button, jrow, 2)
        jrow += 1

        grid_time.addWidget(self.icase_end_label, jrow, 0)
        grid_time.addWidget(self.icase_disp_end_edit, jrow, 1)
        grid_time.addWidget(self.icase_fringe_end_edit, jrow, 2)
        #grid_time.addWidget(self.icase_end_button, jrow, 2)
        jrow += 1

        grid_time.addWidget(self.icase_delta_label, jrow, 0)
        grid_time.addWidget(self.icase_disp_delta_edit, jrow, 1)
        grid_time.addWidget(self.icase_fringe_delta_edit, jrow, 2)
        #grid_time.addWidget(self.icase_delta_button, jrow, 2)
        jrow += 1


        hbox_min = QHBoxLayout()
        hbox_min.addWidget(self.min_value_enable)
        hbox_min.addWidget(self.min_value_label)
        grid_time.addLayout(hbox_min, jrow, 0)
        grid_time.addWidget(self.min_value_edit, jrow, 1)
        grid_time.addWidget(self.min_value_button, jrow, 2)
        jrow += 1

        hbox_max = QHBoxLayout()
        hbox_max.addWidget(self.max_value_enable)
        hbox_max.addWidget(self.max_value_label)
        grid_time.addLayout(hbox_max, jrow, 0)
        grid_time.addWidget(self.max_value_edit, jrow, 1)
        grid_time.addWidget(self.max_value_button, jrow, 2)
        jrow += 1

        grid_time.addWidget(spacer, jrow, 0)
        jrow += 1

        #--------------
        grid_scale = QGridLayout()
        grid_scale.addWidget(self.animation_profile_label, 0, 0)
        grid_scale.addWidget(self.animation_profile_edit, 0, 1)

        #grid_scale.addWidget(self.csv_profile, 1, 0)
        #grid_scale.addWidget(self.csv_profile_edit, 1, 1)
        #grid_scale.addWidget(self.csv_profile_browse_button, 1, 2)

        self.csv_profile = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_button = QPushButton('Browse')

        #box_time = QVBoxLayout()
        # TODO: It's super annoying that the animate time box doesn't
        #       line up with the previous box
        self.box_scale.setLayout(grid_scale)

        self.box_time.setLayout(grid_time)
        #----------

        grid2 = QGridLayout()
        irow = 0
        #grid2.addWidget(self.animate_scale_radio, 8, 0)
        #grid2.addWidget(self.animate_phase_radio, 8, 1)
        #grid2.addWidget(self.animate_time_radio, 8, 2)
        #grid2.addWidget(self.animate_freq_sweeep_radio, 8, 3)

        grid2.addWidget(self.animate_in_gui_checkbox, irow, 0)
        irow += 1

        grid2.addWidget(self.resolution_label, irow, 0)
        grid2.addWidget(self.resolution_edit, irow, 1)
        grid2.addWidget(self.resolution_button, irow, 2)
        irow += 1

        grid2.addWidget(self.browse_folder_label, irow, 0)
        grid2.addWidget(self.browse_folder_edit, irow, 1)
        grid2.addWidget(self.browse_folder_button, irow, 2)
        irow += 1

        grid2.addWidget(self.gif_label, irow, 0)
        grid2.addWidget(self.gif_edit, irow, 1)
        grid2.addWidget(self.gif_button, irow, 2)
        irow += 1

        grid2.addWidget(self.make_images_checkbox, irow, 0)
        #grid2.addWidget(self.overwrite_images_checkbox, irow, 0)
        grid2.addWidget(self.delete_images_checkbox, irow, 1)
        grid2.addWidget(self.make_gif_checkbox, irow, 2)
        irow += 1
        grid2.addWidget(self.repeat_checkbox, irow, 0)
        irow += 1
        grid2.addWidget(spacer, irow, 0)

        grid_hbox = QHBoxLayout()
        grid_hbox.addWidget(spacer)
        grid_hbox.addLayout(grid2)
        grid_hbox.addWidget(spacer)

        # bottom buttons
        step_run_box = QHBoxLayout()
        step_run_box.addWidget(self.step_button)
        step_run_box.addWidget(self.wipe_button)
        step_run_box.addWidget(self.stop_button)
        step_run_box.addWidget(self.run_button)

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        vbox.addWidget(self.box_scale)
        vbox.addWidget(self.box_time)
        #vbox.addLayout(checkboxes)
        vbox.addLayout(grid_hbox)
        vbox.addStretch()
        vbox.addLayout(step_run_box)
        vbox.addLayout(ok_cancel_box)

        if IS_RESULTS_SELECTOR and self.fringe_cases:
            cases = get_cases_from_tree(self.fringe_cases)
            parent = self
            name = 'main'
            data = self.fringe_cases
            choices = cases
            results_widget = ResultsWindow(parent, name, data, choices,
                                           include_clear=False, include_delete=False)
            vbox_results = QVBoxLayout()
            results_widget_label = QLabel('Results:')
            vbox_results.addWidget(results_widget_label)
            vbox_results.addWidget(results_widget)
            hbox_main = QHBoxLayout()
            hbox_main.addLayout(vbox)
            hbox_main.addLayout(vbox_results)
            self.setLayout(hbox_main)
        else:
            self.setLayout(vbox)

    def on_fringe(self, icase):
        """sets the icase fringe"""
        self.icase_fringe_edit.setValue(icase)

    def on_disp(self, icase):
        """sets the icase disp"""
        self.icase_disp_edit.setValue(icase)

    def on_vector(self, icase):
        """sets the icase vector"""
        self.icase_vector_edit.setValue(icase)

    def on_clear_results(self):
        """sink for the right click menu"""
        pass

    def on_step(self):
        """click the Step button"""
        passed, validate_out = self.on_validate()
        if passed:
            try:
                self._make_gif(validate_out, istep=self.istep)
                self.istep += 1
            except IndexError:
                self._make_gif(validate_out, istep=0)
                self.istep += 1
            self.wipe_button.setEnabled(True)

    def on_wipe(self):
        """click the Wipe button"""
        passed, validate_out = self.on_validate(wipe=True)
        if passed:
            self.istep = 0
            self._make_gif(validate_out, istep=self.istep)
            self.wipe_button.setEnabled(False)
            self.stop_button.setEnabled(False)

    def on_stop(self):
        """click the Stop button"""
        #passed, validate_out = self.on_validate()
        #if passed:
            #self._make_gif(validate_out, stop_animation=True)
        if self.is_gui:
            self.gui.stop_animation()

        self.wipe_button.setEnabled(True)
        self.stop_button.setEnabled(False)


    def on_run(self):
        """click the Run button"""
        self.istep = 0
        self.wipe_button.setEnabled(False)
        self.stop_button.setEnabled(True)

        passed, validate_out = self.on_validate()
        if passed:
            self._make_gif(validate_out, istep=None)
        return passed

    def _make_gif(self, validate_out, istep=None, stop_animation=False):
        """interface for making the gif"""
        (icase_fringe, icase_disp, icase_vector, scale, time, fps, animate_in_gui,
         magnify, output_dir, gifbase,
         min_value, max_value) = validate_out
        fps = int(fps)

        gif_filename = None
        if not stop_animation and not animate_in_gui and gifbase is not None:
            if gifbase.lower().endswith('.gif'):
                gifbase = gifbase[:-4]
            gif_filename = os.path.join(output_dir, gifbase + '.gif')

        animate_fringe = self.checkbox_fringe.isChecked()
        animate_vector = self.checkbox_vector.isChecked()

        animate_scale = self.animate_scale_radio.isChecked()
        animate_phase = self.animate_phase_radio.isChecked()
        animate_time = self.animate_time_radio.isChecked()

        if not self.checkbox_vector.isEnabled():
            icase_vector = None

        animate_scale = False
        animate_phase = False
        animate_time = False
        if self._animate_type == 'scale':
            animate_scale = True
        elif self._animate_type == 'phase':
            animate_phase = True
        elif self._animate_type == 'time':
            animate_time = True
        else:
            raise NotImplementedError(self._animate_type)

        make_images = self.make_images_checkbox.isChecked()
        delete_images = self.delete_images_checkbox.isChecked()
        make_gif = self.make_gif_checkbox.isChecked()
        animation_profile = str(self.animation_profile_edit.currentText())

        icase_disp_start = self.icase_disp_start_edit.value()
        icase_disp_end = self.icase_disp_end_edit.value()
        icase_disp_delta = self.icase_disp_delta_edit.value()

        bool_repeat = self.repeat_checkbox.isChecked()  # TODO: change this to an integer
        if bool_repeat:
            nrepeat = 0
        else:
            nrepeat = 1
        #self.out_data['is_shown'] = self.show_radio.isChecked()
        #icase = self._icase

        if self.is_gui:
            self.gui.make_gif(
                gif_filename, scale, istep=istep,
                animate_scale=animate_scale, animate_phase=animate_phase, animate_time=animate_time,
                icase_fringe=icase_fringe, icase_disp=icase_disp, icase_vector=icase_vector,
                animate_fringe=animate_fringe, animate_vector=animate_vector,
                icase_start=icase_disp_start, icase_end=icase_disp_end, icase_delta=icase_disp_delta,
                time=time, animation_profile=animation_profile,
                nrepeat=nrepeat, fps=fps, magnify=magnify,
                make_images=make_images, delete_images=delete_images, make_gif=make_gif,
                stop_animation=stop_animation, animate_in_gui=animate_in_gui,
                min_value=min_value, max_value=max_value,
            )

        self.out_data['clicked_ok'] = True
        self.out_data['close'] = True

    def get_min_max(self, icase):
        if self.is_gui:
            (obj, (i, name)) = self.gui.result_cases[icase]
            min_value, max_value = obj.get_min_max(i, name)
        else:
            return 0., 1.0
        return min_value, max_value

    def on_validate(self, wipe=False):
        """checks to see if the input is valid"""
        # requires no special validation
        icase_fringe, flag0 = check_int(self.icase_fringe_edit)
        icase_disp, unused_flaga = check_int(self.icase_disp_edit)
        icase_vector, unused_flagb = check_int(self.icase_vector_edit)
        #icase_disp = self._icase_disp
        #icase_vector = self._icase_vector

        scale, flag1 = check_float(self.scale_edit)
        time, flag2 = check_float(self.time_edit)
        fps, flag3 = check_float(self.fps_edit)

        min_value = max_value = None
        flag4 = flag5 = True
        if self.min_value_edit.isEnabled():
            min_value, flag4 = check_float(self.min_value_edit)
        if self.max_value_edit.isEnabled():
            max_value, flag5 = check_float(self.max_value_edit)

        if wipe:
            animate_in_gui = False
            scale = 0.
            flag1 = True
        else:
            animate_in_gui = self.animate_in_gui_checkbox.isChecked()
            if scale == 0.0:
                self.scale_edit.setStyleSheet("QLineEdit{background: red;}")
                flag1 = False

        if animate_in_gui or wipe:
            passed = all([flag0, flag1, flag2, flag3, flag4, flag5])
            magnify, output_dir, gifbase = None, None, None
        else:
            magnify, flag6 = check_int(self.resolution_edit)
            output_dir, flag7 = check_path(self.browse_folder_edit)
            gifbase, flag8 = check_name_str(self.gif_edit)
            passed = all([flag0, flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8])
        return passed, (icase_fringe, icase_disp, icase_vector, scale, time, fps, animate_in_gui,
                        magnify, output_dir, gifbase, min_value, max_value)

    #def on_ok(self):
        #"""click the OK button"""
        #passed = self.on_apply()
        #if passed:
            #self.win_parent._animation_window_shown = False
            #self.close()
            ##self.destroy()

    def on_cancel(self):
        """click the Cancel button"""
        self.on_stop()
        self.out_data['close'] = True
        self.close()
Beispiel #10
0
class DepthGUI(QMainWindow):
    def __init__(self):
        super(DepthGUI, self).__init__()

        self.display_string = None

        # Serial port config
        self.ser = serial.Serial()
        self.ser.baudrate = 19200

        self.depth_stream = None
        self._prev_port = None

        self.setup_ui()

    def setup_ui(self):
        self.setWindowTitle('Neuroport DBS - Electrodes Depth')
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.move(WINDOWDIMS_DEPTH[0], WINDOWDIMS_DEPTH[1])
        self.setFixedSize(WINDOWDIMS_DEPTH[2], WINDOWDIMS_DEPTH[3])

        self.show()

        self.plot_widget = QWidget()
        self.setCentralWidget(self.plot_widget)

        # define Qt GUI elements
        v_layout = QVBoxLayout()
        v_layout.setSpacing(0)
        v_layout.setContentsMargins(10, 0, 10, 10)

        h_layout = QHBoxLayout()

        self.comboBox_com_port = QComboBox()
        h_layout.addWidget(self.comboBox_com_port)

        self.pushButton_open = QPushButton("Open")
        h_layout.addWidget(self.pushButton_open)
        h_layout.addStretch()

        self.label_offset = QLabel("Offset: ")
        h_layout.addWidget(self.label_offset)

        self.doubleSpinBox_offset = QDoubleSpinBox()
        self.doubleSpinBox_offset.setMinimum(-100.00)
        self.doubleSpinBox_offset.setMaximum(100.00)
        self.doubleSpinBox_offset.setSingleStep(1.00)
        self.doubleSpinBox_offset.setDecimals(2)
        self.doubleSpinBox_offset.setValue(-10.00)
        self.doubleSpinBox_offset.setFixedWidth(60)
        h_layout.addWidget(self.doubleSpinBox_offset)

        h_layout.addStretch()

        h_layout.addWidget(QLabel("Stream to :"))

        self.chk_NSP = QCheckBox("NSP")
        self.chk_NSP.setChecked(True)
        h_layout.addWidget(self.chk_NSP)

        h_layout.addSpacing(5)

        self.chk_LSL = QCheckBox("LSL")
        self.chk_LSL.clicked.connect(self.on_chk_LSL_clicked)
        self.chk_LSL.click(
        )  # default is enabled, click call to trigger LSL stream creation.
        h_layout.addWidget(self.chk_LSL)

        h_layout.addSpacing(5)

        send_btn = QPushButton("Send")
        send_btn.clicked.connect(self.send)

        h_layout.addWidget(send_btn)
        h_layout.addSpacing(5)

        quit_btn = QPushButton('X')
        quit_btn.setMaximumWidth(20)
        quit_btn.clicked.connect(QApplication.instance().quit)

        quit_btn.setStyleSheet("QPushButton { color: white; "
                               "background-color : red; "
                               "border-color : red; "
                               "border-width: 2px}")

        h_layout.addWidget(quit_btn)

        v_layout.addLayout(h_layout)

        # define Qt GUI elements
        # add a frame for the LCD numbers
        self.lcd_frame = QFrame()
        self.lcd_frame.setFrameShape(1)
        lcd_layout = QGridLayout()
        self.lcd_frame.setLayout(lcd_layout)

        # RAW reading from DDU
        self.raw_ddu = QLCDNumber()
        self.raw_ddu.setDigitCount(7)
        self.raw_ddu.setFrameShape(0)
        self.raw_ddu.setSmallDecimalPoint(True)
        self.raw_ddu.setFixedHeight(50)
        self.raw_ddu.display("{0:.3f}".format(0))
        lcd_layout.addWidget(self.raw_ddu, 0, 3, 2, 3)

        self.offset_ddu = QLCDNumber()
        self.offset_ddu.setDigitCount(7)
        self.offset_ddu.setFixedHeight(150)
        self.offset_ddu.display("{0:.3f}".format(-10))
        self.offset_ddu.setFrameShape(0)
        lcd_layout.addWidget(self.offset_ddu, 2, 0, 5, 6)
        v_layout.addWidget(self.lcd_frame)

        self.plot_widget.setLayout(v_layout)

        # Populate control panel items
        for port in serial.tools.list_ports.comports():
            self.comboBox_com_port.addItem(port.device)
        self.comboBox_com_port.addItem("cbsdk playback")

        # Connect signals & slots
        self.pushButton_open.clicked.connect(self.on_open_clicked)
        self.comboBox_com_port.currentIndexChanged.connect(
            self.on_comboBox_com_port_changed)
        # TODO: Add signal for comboBox_com_port --> when cbsdk playback, uncheck NSP then re-open connection.

    def on_chk_LSL_clicked(self, state):
        print(f"LSL clicked state: {state}")
        if self.chk_LSL.isChecked():
            outlet_info = pylsl.StreamInfo(name='electrode_depth',
                                           type='depth',
                                           channel_count=1,
                                           nominal_srate=pylsl.IRREGULAR_RATE,
                                           channel_format=pylsl.cf_float32,
                                           source_id='depth1214')
            self.depth_stream = pylsl.StreamOutlet(outlet_info)
        else:
            self.depth_stream = None

    def _do_close(self, from_port):
        if from_port == "cbsdk playback":
            CbSdkConnection().disconnect()
        else:
            self.ser.close()
        self.pushButton_open.setText("Open")

    def on_comboBox_com_port_changed(self, new_ix):
        # If a connection was already open, close it before proceeding.
        if self.pushButton_open.text() == "Close":
            self._do_close(self._prev_port)

        # at this point the Open/Close pushbutton should show: Open
        # we will only enable/disable the Send to NSP button to leave the current checked status.
        # The default should be checked.
        if self.comboBox_com_port.currentText() == "cbsdk playback":
            # If switching _to_ cbsdk playback, disable sending out comments.
            self.chk_NSP.setEnabled(False)

        elif self._prev_port == "cbsdk playback":
            # If switching _from_ cbsdk playback, re-enable sending out comments.
            self.chk_NSP.setEnabled(True)

        self._prev_port = self.comboBox_com_port.currentText()

    def on_open_clicked(self):
        com_port = self.comboBox_com_port.currentText()
        cmd_text = self.pushButton_open.text()
        if cmd_text == 'Open':

            if com_port == "cbsdk playback":
                CbSdkConnection().connect()
                CbSdkConnection().cbsdk_config = {
                    'reset': True,
                    'get_events': False,
                    'get_comments': True,
                    'buffer_parameter': {
                        'comment_length': 10
                    }
                }
                self.pushButton_open.setText("Close")
            else:
                if self.chk_NSP.isEnabled() and self.chk_NSP.isChecked():
                    CbSdkConnection().connect()
                    CbSdkConnection().cbsdk_config = {
                        'reset': True,
                        'get_events': False,
                        'get_comments': False
                    }

                if not self.ser.is_open:
                    self.ser.port = com_port
                    try:
                        self.ser.open()  # TODO: Add timeout; Add error.
                        self.ser.write('AXON+\r'.encode())
                    except serial.serialutil.SerialException:
                        print("Could not open serial port")
                    finally:
                        self.pushButton_open.setText(
                            "Close" if self.ser.is_open else "Open")
        else:
            self._do_close(com_port)

    def update(self):
        # Added new_value handling for playback if we ever want to post-process depth
        # on previously recorded sessions.
        new_value = False
        out_value = None

        if self.comboBox_com_port.currentText() == "cbsdk playback":
            cbsdk_conn = CbSdkConnection()
            if cbsdk_conn.is_connected:
                comments = cbsdk_conn.get_comments()
                if comments:
                    comment_strings = [x[1].decode('utf8') for x in comments]
                else:
                    comment_strings = ""
                dtts = []
                for comm_str in comment_strings:
                    if 'DTT:' in comm_str:
                        dtts.append(float(comm_str[4:]))
                if len(dtts) > 0:
                    out_value = dtts[-1]
                    new_value = True
                    self.offset_ddu.display("{0:.3f}".format(out_value))
                    offset = self.doubleSpinBox_offset.value()
                    self.raw_ddu.display("{0:.3f}".format(out_value - offset))

        elif self.ser.is_open:
            in_str = self.ser.readline().decode('utf-8').strip()
            if in_str:
                try:
                    in_value = float(in_str)
                    # in_value /= DDUSCALEFACTOR  # Uncomment this for FHC DDU V2.

                    self.raw_ddu.display("{0:.3f}".format(in_value))

                    out_value = in_value + self.doubleSpinBox_offset.value()
                    display_string = "{0:.3f}".format(out_value)
                    self.offset_ddu.display(display_string)

                    # Check if new value
                    if display_string != self.display_string:
                        new_value = True
                        self.display_string = display_string

                    # Push to NSP
                    cbsdk_conn = CbSdkConnection()
                    if cbsdk_conn.is_connected:
                        if self.chk_NSP.isChecked() and self.chk_NSP.isEnabled(
                        ) and new_value:
                            cbsdk_conn.set_comments("DTT:" + display_string)
                    else:
                        # try connecting if not connected but button is active
                        if self.chk_NSP.isChecked() and self.chk_NSP.isEnabled(
                        ):
                            cbsdk_conn.connect()
                            cbsdk_conn.cbsdk_config = {
                                'reset': True,
                                'get_events': False,
                                'get_comments': False
                            }
                        # set button to connection status
                        self.chk_NSP.setChecked(cbsdk_conn.is_connected)

                except ValueError:
                    print("DDU result: {}".format(in_str))

        # Push to LSL
        if self.depth_stream is not None and new_value:
            self.depth_stream.push_sample([out_value])

    def send(self):
        self.display_string = None  # make sure the update function runs
        self.update()
Beispiel #11
0
 def createEditor(self, parent, option, index):
     editor = QDoubleSpinBox(parent)
     editor.setMinimum(0)
     editor.setDecimals(5)
     editor.setSingleStep(0.0001)
     return editor
Beispiel #12
0
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self._default_font_size = data['font_size']
        self._default_text_size = 14
        self._default_annotation_size = 18
        self._default_coord_scale = 0.05 * 100.
        self._default_coord_text_scale = 0.5 * 100.
        self._default_clipping_min = data['min_clip']
        self._default_clipping_max = data['max_clip']
        #self._default_annotation_size = data['annotation_size'] # int
        #self.default_magnify = data['magnify']

        self.dim_max = data['dim_max']
        self._use_gradient_background = data['use_gradient_background'] # bool
        self._annotation_size = data['annotation_size'] # int

        #self.out_data = data
        self._picker_size = data['picker_size'] * 100.
        self._coord_scale = data['coord_scale'] * 100.
        self._coord_text_scale = data['coord_text_scale'] * 100.
        self._magnify = data['magnify']
        self._text_size = data['text_size']

        self.annotation_color_float, self.annotation_color_int = _check_color(
            data['annotation_color'])
        self.background_color_float, self.background_color_int = _check_color(
            data['background_color'])
        self.background_color2_float, self.background_color2_int = _check_color(
            data['background_color2'])
        self.text_color_float, self.text_color_int = _check_color(
            data['text_color'])

        self.setWindowTitle('Preferences')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        self.on_gradient_scale()
        #self.show()

    def create_widgets(self):
        """creates the display window"""
        # Text Size
        self.font_size_label = QLabel("Font Size:")
        self.font_size_edit = QSpinBox(self)
        self.font_size_edit.setValue(self._default_font_size)
        self.font_size_edit.setRange(7, 20)
        self.font_size_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # Annotation Color
        self.annotation_color_label = QLabel("Annotation Color:")
        self.annotation_color_edit = QPushButtonColor(self.annotation_color_int)
        self.annotation_color_label.hide()
        self.annotation_color_edit.hide()
        #-----------------------------------------------------------------------
        # Text Color
        self.text_size_label = QLabel("Text Size:")
        self.text_size_edit = QSpinBox(self)
        self.text_size_edit.setValue(self._default_text_size)
        self.text_size_edit.setRange(7, 30)
        self.text_size_button = QPushButton("Default")

        # Text Color
        self.text_color_label = QLabel("Text Color:")
        self.text_color_edit = QPushButtonColor(self.text_color_int)

        #-----------------------------------------------------------------------
        # Background Color
        self.background_color_label = QLabel("Btm Background Color:")
        self.background_color_edit = QPushButtonColor(self.background_color_int)

        # Background Color2
        self.gradient_scale_label = QLabel("Gradient Background:")
        self.gradient_scale_checkbox = QCheckBox()
        self.gradient_scale_checkbox.setChecked(self._use_gradient_background)

        self.background_color2_label = QLabel("Top Background Color:")
        self.background_color2_edit = QPushButtonColor(self.background_color2_int)

        #-----------------------------------------------------------------------
        # Annotation Size
        self.annotation_size_label = QLabel("Annotation Size:")
        self.annotation_size_edit = QSpinBox(self)
        self.annotation_size_edit.setRange(1, 500)
        self.annotation_size_edit.setValue(self._annotation_size)
        self.annotation_size_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # Picker Size
        self.picker_size_label = QLabel("Picker Size (% of Screen):")
        self.picker_size_edit = QDoubleSpinBox(self)
        self.picker_size_edit.setRange(0., 10.)

        log_dim = log10(self.dim_max)
        decimals = int(ceil(abs(log_dim)))

        decimals = max(6, decimals)
        self.picker_size_edit.setDecimals(decimals)
        self.picker_size_edit.setSingleStep(10. / 5000.)
        self.picker_size_edit.setValue(self._picker_size)

        #-----------------------------------------------------------------------
        # Clipping Min
        self.clipping_min_label = QLabel("Clipping Min:")
        self.clipping_min_edit = QLineEdit(str(self._default_clipping_min))
        self.clipping_min_button = QPushButton("Default")

        # Clipping Max
        self.clipping_max_label = QLabel("Clipping Max:")
        self.clipping_max_edit = QLineEdit(str(self._default_clipping_max))
        self.clipping_max_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        self.coord_scale_label = QLabel('Coordinate System Scale:')
        self.coord_scale_button = QPushButton("Default")

        self.coord_scale_edit = QDoubleSpinBox(self)
        self.coord_scale_edit.setRange(0.1, 100.)
        self.coord_scale_edit.setDecimals(3)
        self.coord_scale_edit.setSingleStep(2.5)
        self.coord_scale_edit.setValue(self._coord_scale)

        self.coord_text_scale_label = QLabel('Coordinate System Text Scale:')
        self.coord_text_scale_button = QPushButton("Default")

        self.coord_text_scale_edit = QDoubleSpinBox(self)
        self.coord_text_scale_edit.setRange(0.1, 200.)
        self.coord_text_scale_edit.setDecimals(3)
        self.coord_text_scale_edit.setSingleStep(2.5)
        self.coord_text_scale_edit.setValue(self._coord_text_scale)

        #-----------------------------------------------------------------------
        self.magnify_label = QLabel('Screenshot Magnify:')
        self.magnify_edit = QSpinBox(self)
        self.magnify_edit.setMinimum(1)
        self.magnify_edit.setMaximum(10)
        self.magnify_edit.setValue(self._magnify)

        #-----------------------------------------------------------------------
        # closing
        self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

    #def create_legend_widgets(self):
        #"""
        #Creates the widgets for the legend control

        #Name    Itailic  Bold     Font
        #====    =======  =====  ========
        #Title    check   check  pulldown
        #Label    check   check  pulldown
        #"""
        #self.name_label = QLabel("Name:")
        #self.italic_label = QLabel("Italic:")
        #self.bold_label = QLabel("Bold:")
        #self.font_label = QLabel("Font:")
        #self.legend_label = QLabel("Legend:")

        #self.legend_title_name = QLabel("Title")
        #self.legend_title_italic_check = QCheckBox()
        #self.legend_title_bold_check = QCheckBox()
        #self.legend_title_font_edit = QComboBox()
        #self.legend_title_font_edit.addItems(['cat', 'dog', 'frog'])

        #self.legend_label_italic_name = QLabel("Label")
        #self.legend_label_italic_check = QCheckBox()
        #self.legend_label_bold_check = QCheckBox()
        #self.legend_label_font_edit = QComboBox()
        #self.legend_label_font_edit.addItems(['cat2', 'dog2', 'frog2'])

    #def create_legend_layout(self):
        #"""
        #Creates the layout for the legend control

        #Name    Itailic  Bold     Font
        #====    =======  =====  ========
        #Title    check   check  pulldown
        #Label    check   check  pulldown
        #"""
        #grid2 = QGridLayout()
        #grid2.addWidget(self.legend_label, 0, 0)

        #grid2.addWidget(self.name_label, 1, 0)
        #grid2.addWidget(self.italic_label, 1, 1)
        #grid2.addWidget(self.bold_label, 1, 2)
        #grid2.addWidget(self.font_label, 1, 3)

        #grid2.addWidget(self.legend_title_name, 2, 0)
        #grid2.addWidget(self.legend_title_italic_check, 2, 1)
        #grid2.addWidget(self.legend_title_bold_check, 2, 2)
        #grid2.addWidget(self.legend_title_font_edit, 2, 3)

        #grid2.addWidget(self.legend_label_italic_name, 3, 0)
        #grid2.addWidget(self.legend_label_italic_check, 3, 1)
        #grid2.addWidget(self.legend_label_bold_check, 3, 2)
        #grid2.addWidget(self.legend_label_font_edit, 3, 3)
        #return grid2

    def create_layout(self):
        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.font_size_label, irow, 0)
        grid.addWidget(self.font_size_edit, irow, 1)
        grid.addWidget(self.font_size_button, irow, 2)
        irow += 1

        grid.addWidget(self.gradient_scale_label, irow, 0)
        grid.addWidget(self.gradient_scale_checkbox, irow, 1)
        irow += 1

        grid.addWidget(self.background_color2_label, irow, 0)
        grid.addWidget(self.background_color2_edit, irow, 1)
        irow += 1

        grid.addWidget(self.background_color_label, irow, 0)
        grid.addWidget(self.background_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.text_color_label, irow, 0)
        grid.addWidget(self.text_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.text_size_label, irow, 0)
        grid.addWidget(self.text_size_edit, irow, 1)
        grid.addWidget(self.text_size_button, irow, 2)
        irow += 1

        grid.addWidget(self.annotation_color_label, irow, 0)
        grid.addWidget(self.annotation_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.annotation_size_label, irow, 0)
        grid.addWidget(self.annotation_size_edit, irow, 1)
        grid.addWidget(self.annotation_size_button, irow, 2)
        irow += 1

        #grid.addWidget(self.clipping_min_label, irow, 0)
        #grid.addWidget(self.clipping_min_edit, irow, 1)
        #grid.addWidget(self.clipping_min_button, irow, 2)
        #irow += 1

        #grid.addWidget(self.clipping_max_label, irow, 0)
        #grid.addWidget(self.clipping_max_edit, irow, 1)
        #grid.addWidget(self.clipping_max_button, irow, 2)
        #irow += 1

        grid.addWidget(self.coord_scale_label, irow, 0)
        grid.addWidget(self.coord_scale_edit, irow, 1)
        grid.addWidget(self.coord_scale_button, irow, 2)
        irow += 1

        grid.addWidget(self.coord_text_scale_label, irow, 0)
        grid.addWidget(self.coord_text_scale_edit, irow, 1)
        grid.addWidget(self.coord_text_scale_button, irow, 2)
        irow += 1

        #-----------------------------------------------
        grid.addWidget(self.magnify_label, irow, 0)
        grid.addWidget(self.magnify_edit, irow, 1)
        irow += 1

        grid.addWidget(self.picker_size_label, irow, 0)
        grid.addWidget(self.picker_size_edit, irow, 1)
        irow += 1

        #self.create_legend_widgets()
        #grid2 = self.create_legend_layout()
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        #vbox.addStretch()
        #vbox.addLayout(grid2)
        vbox.addStretch()

        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        self.font_size_button.clicked.connect(self.on_default_font_size)
        self.font_size_edit.valueChanged.connect(self.on_font)

        self.annotation_size_edit.editingFinished.connect(self.on_annotation_size)
        self.annotation_size_edit.valueChanged.connect(self.on_annotation_size)
        self.annotation_color_edit.clicked.connect(self.on_annotation_color)
        self.annotation_size_button.clicked.connect(self.on_default_annotation_size)

        self.background_color_edit.clicked.connect(self.on_background_color)
        self.background_color2_edit.clicked.connect(self.on_background_color2)
        self.gradient_scale_checkbox.clicked.connect(self.on_gradient_scale)

        self.text_color_edit.clicked.connect(self.on_text_color)
        self.text_size_edit.valueChanged.connect(self.on_text_size)
        self.text_size_button.clicked.connect(self.on_default_text_size)

        self.picker_size_edit.valueChanged.connect(self.on_picker_size)
        self.picker_size_edit.editingFinished.connect(self.on_picker_size)

        self.coord_scale_edit.valueChanged.connect(self.on_coord_scale)
        self.coord_scale_edit.editingFinished.connect(self.on_coord_scale)
        self.coord_scale_button.clicked.connect(self.on_default_coord_scale)

        self.coord_text_scale_edit.valueChanged.connect(self.on_coord_text_scale)
        self.coord_text_scale_edit.editingFinished.connect(self.on_coord_text_scale)
        self.coord_text_scale_button.clicked.connect(self.on_default_coord_text_scale)

        self.magnify_edit.valueChanged.connect(self.on_magnify)
        self.magnify_edit.editingFinished.connect(self.on_magnify)

        self.clipping_min_button.clicked.connect(self.on_default_clipping_min)
        self.clipping_max_button.clicked.connect(self.on_default_clipping_max)

        self.apply_button.clicked.connect(self.on_apply)
        self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)
        # closeEvent

    def on_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)

    def on_annotation_size(self, value=None):
        """update the annotation size"""
        if value is None:
            value = int(self.annotation_size_edit.text())
        self._annotation_size = value
        #self.on_apply(force=True)
        #self.min_edit.setText(str(self._default_min))
        #self.min_edit.setStyleSheet("QLineEdit{background: white;}")
        self.update_annotation_size_color()

    def update_annotation_size_color(self):
        if self.win_parent is not None:
            self.win_parent.settings.set_annotation_size_color(size=self._annotation_size)

    def on_gradient_scale(self):
        is_checked = self.gradient_scale_checkbox.isChecked()
        self.background_color2_label.setEnabled(is_checked)
        self.background_color2_edit.setEnabled(is_checked)
        if self.win_parent is not None:
            self.win_parent.settings.set_gradient_background(use_gradient_background=is_checked)

    def on_annotation_color(self):
        rgb_color_ints = self.annotation_color_int
        title = "Choose an annotation color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.annotation_color_edit, rgb_color_ints, title)
        if passed:
            self.annotation_color_int = rgb_color_ints
            self.annotation_color_float = rgb_color_floats
            self.update_annotation_size_color()

    def on_background_color(self):
        """ Choose a background color"""
        title = "Choose a primary background color"
        rgb_color_ints = self.background_color_int
        color_edit = self.background_color_edit
        func_name = 'set_background_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.background_color_int = rgb_color_ints
            self.background_color_float = rgb_color_floats

    def on_background_color2(self):
        """ Choose a background color"""
        title = "Choose a secondary background color"
        rgb_color_ints = self.background_color2_int
        color_edit = self.background_color2_edit
        func_name = 'set_background_color2'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.background_color2_int = rgb_color_ints
            self.background_color2_float = rgb_color_floats

    def _background_color(self, title, color_edit, rgb_color_ints, func_name):
        """helper method for ``on_background_color`` and ``on_background_color2``"""
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            color_edit, rgb_color_ints, title)
        if passed:
            if self.win_parent is not None:
                settings = self.win_parent.settings
                func_background_color = getattr(settings, func_name)
                func_background_color(rgb_color_floats)
        return passed, rgb_color_ints, rgb_color_floats

    def on_text_color(self):
        """ Choose a text color """
        rgb_color_ints = self.text_color_int
        title = "Choose a text color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.text_color_edit, rgb_color_ints, title)
        if passed:
            self.text_color_int = rgb_color_ints
            self.text_color_float = rgb_color_floats
            if self.win_parent is not None:
                self.win_parent.settings.set_text_color(rgb_color_floats)

    def on_default_text_size(self):
        self.text_size_edit.setValue(self._default_text_size)
        self.on_text_size(self._default_text_size)

    def on_text_size(self, value=None):
        if value is None:
            value = self.text_size_edit.value()
        self._text_size = value
        if self.win_parent is not None:
            self.win_parent.settings.set_text_size(value)

    def on_color(self, color_edit, rgb_color_ints, title):
        """pops a color dialog"""
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    title)
        if not col.isValid():
            return False, rgb_color_ints, None

        color_float = col.getRgbF()[:3]  # floats
        color_int = [int(colori * 255) for colori in color_float]

        assert isinstance(color_float[0], float), color_float
        assert isinstance(color_int[0], int), color_int

        color_edit.setStyleSheet(
            "QPushButton {"
            "background-color: rgb(%s, %s, %s);" % tuple(color_int) +
            #"border:1px solid rgb(255, 170, 255); "
            "}")
        return True, color_int, color_float

    def on_picker_size(self):
        self._picker_size = float(self.picker_size_edit.text())
        if self.win_parent is not None:
            self.win_parent.element_picker_size = self._picker_size / 100.
        #self.on_apply(force=True)

    def on_magnify(self, value=None):
        if value is None:
            value = self.magnify_edit.value()
        self._magnify = value
        if self.win_parent is not None:
            self.win_parent.settings.set_magnify(value)

    #---------------------------------------------------------------------------
    def on_coord_scale(self, value=None):
        if value is None:
            value = self.coord_scale_edit.value()
        self._coord_scale = value
        if self.win_parent is not None:
            self.win_parent.settings.set_coord_scale(value / 100.)

    def on_default_coord_scale(self):
        self.coord_scale_edit.setValue(self._default_coord_scale)
        self.on_coord_scale(self._default_coord_scale)

    def on_coord_text_scale(self, value=None):
        if value is None:
            value = self.coord_text_scale_edit.value()
        self._coord_text_scale = value
        if self.win_parent is not None:
            self.win_parent.settings.set_coord_text_scale(value / 100.)

    def on_default_coord_text_scale(self):
        self.coord_text_scale_edit.setValue(self._default_coord_text_scale)
        self.on_coord_text_scale(self._default_coord_text_scale)

    #---------------------------------------------------------------------------
    def on_default_font_size(self):
        self.font_size_edit.setValue(self._default_font_size)
        self.on_font(self._default_font_size)

    def on_default_annotation_size(self):
        self.annotation_size_edit.setValue(self._default_annotation_size)
        self.on_annotation_size(self._default_annotation_size)

    def on_default_clipping_min(self):
        self.clipping_min_edit.setText(str(self._default_clipping_min))
        self.clipping_min_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_clipping_max(self):
        self.clipping_max_edit.setText(str(self._default_clipping_max))
        self.clipping_max_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_validate(self):
        font_size_value, flag0 = check_float(self.font_size_edit)
        annotation_size_value, flag1 = check_float(self.annotation_size_edit)
        assert isinstance(self.annotation_color_float[0], float), self.annotation_color_float
        assert isinstance(self.annotation_color_int[0], int), self.annotation_color_int
        picker_size_value, flag2 = check_float(self.picker_size_edit)

        clipping_min_value, flag3 = check_label_float(self.clipping_min_edit)
        clipping_max_value, flag4 = check_label_float(self.clipping_max_edit)

        if all([flag0, flag1, flag2, flag3, flag4]):
            self._annotation_size = annotation_size_value
            self._picker_size = picker_size_value

            self.out_data['font_size'] = int(font_size_value)
            self.out_data['min_clip'] = min(clipping_min_value, clipping_max_value)
            self.out_data['max_clip'] = max(clipping_min_value, clipping_max_value)
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self, force=False):
        passed = self.on_validate()

        if (passed or force) and self.win_parent is not None:
            self.win_parent.settings.on_set_font_size(self.out_data['font_size'])

            #self.win_parent.settings.set_annotation_size_color(self._annotation_size)
            #self.win_parent.element_picker_size = self._picker_size / 100.
        if passed and self.win_parent is not None:
            self.win_parent.clipping_obj.apply_clipping(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
Beispiel #13
0
class DimensionNonIntegrated(Dimension):
    binningChanged = Signal()
    """
    A dimension that can either be sliced through or rebinned. It
    has additional properties for either number_of_bins or thickness

    from mantidqt.widgets.sliceviewer.dimensionwidget import DimensionMDE
    from qtpy.QtWidgets import QApplication
    app = QApplication([])
    window = DimensionNonIntegrated({'minimum':-1.1, 'number_of_bins':11,
                                     'width':0.2, 'name':'Dim0', 'units':'A'})
    window.show()
    app.exec_()
    """
    def __init__(self, dim_info, number=0, state=State.NONE, parent=None):
        # hack in a number_of_bins for MDEventWorkspace
        if dim_info['type'] == 'MDE':
            dim_info['number_of_bins'] = 100
            dim_info['width'] = (dim_info['maximum'] -
                                 dim_info['minimum']) / 100

        self.spinBins = QSpinBox()
        self.spinBins.setRange(2, 9999)
        self.spinBins.setValue(dim_info['number_of_bins'])
        self.spinBins.hide()
        self.spinBins.setMinimumWidth(110)
        self.spinThick = QDoubleSpinBox()
        self.spinThick.setRange(0.001, 999)
        self.spinThick.setValue(0.1)
        self.spinThick.setSingleStep(0.1)
        self.spinThick.setDecimals(3)
        self.spinThick.setMinimumWidth(110)
        self.rebinLabel = QLabel("thick")
        self.rebinLabel.setMinimumWidth(44)

        super().__init__(dim_info, number, state, parent)

        self.spinBins.valueChanged.connect(self.binningChanged)
        self.spinThick.valueChanged.connect(self.valueChanged)

        self.layout.addWidget(self.spinBins)
        self.layout.addWidget(self.spinThick)
        self.layout.addWidget(self.rebinLabel)

    def get_bins(self):
        return int(self.spinBins.value())

    def get_thickness(self):
        return float(self.spinThick.value())

    def set_state(self, state):
        super().set_state(state)
        if self.state == State.X:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.Y:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.NONE:
            self.spinBins.hide()
            self.spinThick.show()
            self.rebinLabel.setText('thick')
        else:
            self.spinBins.hide()
            self.spinThick.hide()
            self.rebinLabel.hide()

    def set_value(self, value):
        """Override the set_value for MDE, this allows the exact value to be
        set instead of limiting to the value of the slider. This
        allows when selecting a peak to go to the exact layer where
        the peak is.

        """
        self.value = value
        # temporary disable updating value from slider change
        self.update_value_from_slider = False
        self.update_slider()
        self.update_value_from_slider = True
        self.update_spinbox()
Beispiel #14
0
class EditBoundaryConditions(QDialog):
    def __init__(self, data, win_parent=None):
        """
        +---------+
        | Painter |
        +---------+---------+
        |  Name1            |
        |  Name2            |
        |  Name3            |
        |  Name4            |
        |                   |
        | x by cell   ___   |
        | x by angle  ___   |
        |                   |
        |   box elements    |
        |                   |
        |   Add    Remove   |
        |                   |
        | Apply  OK  Cancel |
        +-------------------+
        """
        QDialog.__init__(self, win_parent)
        self.setWindowTitle('Edit Boundary Conditions')

        #default
        self.win_parent = win_parent
        self.out_data = data

        self.keys = sorted(data.keys())
        keys = self.keys
        nrows = len(keys)
        self.active_key = keys[0]

        self._use_old_table = False
        items = keys
        header_labels = ['Groups']
        table_model = Model(items, header_labels, self)
        view = SingleChoiceQTableView(self)  #Call your custom QTableView here
        view.setModel(table_model)
        #view.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch)  #TODO: fixme
        self.table = view

        actor_obj = data[self.active_key]
        name = actor_obj.name
        line_width = actor_obj.line_width
        point_size = actor_obj.point_size
        opacity = actor_obj.opacity
        color = actor_obj.color
        show = actor_obj.is_visible
        self.representation = actor_obj.representation

        table = self.table
        #headers = [QtCore.QString('Groups')]

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        self._default_is_apply = False
        self.name = QLabel("Name:")
        self.name_edit = QLineEdit(str(name))
        self.name_edit.setDisabled(True)

        self.color = QLabel("Color:")
        self.color_edit = QPushButton()
        #self.color_edit.setFlat(True)

        color = self.out_data[self.active_key].color
        qcolor = QtGui.QColor()
        qcolor.setRgb(*color)
        #print('color =%s' % str(color))
        palette = QtGui.QPalette(
            self.color_edit.palette())  # make a copy of the palette
        #palette.setColor(QtGui.QPalette.Active, QtGui.QPalette.Base, \
        #qcolor)
        palette.setColor(QtGui.QPalette.Background,
                         QtGui.QColor('blue'))  # ButtonText
        self.color_edit.setPalette(palette)

        self.color_edit.setStyleSheet("QPushButton {"
                                      "background-color: rgb(%s, %s, %s);" %
                                      tuple(color) +
                                      #"border:1px solid rgb(255, 170, 255); "
                                      "}")

        self.opacity = QLabel('Opacity:')
        self.opacity_edit = QDoubleSpinBox(self)
        self.opacity_edit.setRange(0.1, 1.0)
        self.opacity_edit.setDecimals(1)
        self.opacity_edit.setSingleStep(0.1)
        self.opacity_edit.setValue(opacity)

        self.line_width = QLabel('Line Width:')
        self.line_width_edit = QSpinBox(self)
        self.line_width_edit.setRange(1, 10)
        self.line_width_edit.setSingleStep(1)
        self.line_width_edit.setValue(line_width)
        if self.representation in ['point', 'surface']:
            self.line_width.setEnabled(False)
            self.line_width_edit.setEnabled(False)

        self.point_size = QLabel('Point Size:')
        self.point_size_edit = QSpinBox(self)
        self.point_size_edit.setRange(1, 10)
        self.point_size_edit.setSingleStep(1)
        self.point_size_edit.setValue(point_size)
        if self.representation in ['wire', 'surface']:
            self.point_size.setEnabled(False)
            self.point_size_edit.setEnabled(False)

        # show/hide
        self.checkbox_show = QCheckBox("Show")
        self.checkbox_hide = QCheckBox("Hide")
        self.checkbox_show.setChecked(show)
        self.checkbox_hide.setChecked(not show)

        # closing
        self.apply_button = QPushButton("Apply")
        #if self._default_is_apply:
        #self.apply_button.setDisabled(True)

        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

        self.create_layout()
        self.set_connections()

    def update_active_key(self, index):
        old_obj = self.out_data[self.active_key]
        old_obj.line_width = self.line_width_edit.value()
        old_obj.point_size = self.point_size_edit.value()
        old_obj.opacity = self.opacity_edit.value()
        old_obj.is_visible = self.checkbox_show.isChecked()

        name = index.data()
        #i = self.keys.index(self.active_key)

        self.active_key = name
        self.name_edit.setText(name)
        obj = self.out_data[name]
        line_width = obj.line_width
        point_size = obj.point_size
        opacity = obj.opacity
        representation = obj.representation
        is_visible = obj.is_visible

        self.color_edit.setStyleSheet("QPushButton {"
                                      "background-color: rgb(%s, %s, %s);" %
                                      tuple(obj.color) +
                                      #"border:1px solid rgb(255, 170, 255); "
                                      "}")
        self.line_width_edit.setValue(line_width)
        self.point_size_edit.setValue(point_size)
        if self.representation != representation:
            self.representation = representation

            if self.representation == 'point':
                self.point_size.setEnabled(True)
                self.point_size_edit.setEnabled(True)
            else:
                self.point_size.setEnabled(False)
                self.point_size_edit.setEnabled(False)

            if self.representation == ['wire']:
                self.line_width.setEnabled(True)
                self.line_width_edit.setEnabled(True)
            else:
                self.line_width.setEnabled(False)
                self.line_width_edit.setEnabled(False)
            #if self.representation in ['wire', 'surface']:

        self.opacity_edit.setValue(opacity)
        self.checkbox_show.setChecked(is_visible)
        self.checkbox_hide.setChecked(not is_visible)

    #def on_name_select(self):
    #print('on_name_select')
    #return

    def create_layout(self):
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.name, irow, 0)
        grid.addWidget(self.name_edit, irow, 1)
        irow += 1

        grid.addWidget(self.color, irow, 0)
        grid.addWidget(self.color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.opacity, irow, 0)
        grid.addWidget(self.opacity_edit, irow, 1)
        irow += 1

        grid.addWidget(self.line_width, irow, 0)
        grid.addWidget(self.line_width_edit, irow, 1)
        irow += 1

        grid.addWidget(self.point_size, irow, 0)
        grid.addWidget(self.point_size_edit, irow, 1)
        irow += 1

        checkboxs = QButtonGroup(self)
        checkboxs.addButton(self.checkbox_show)
        checkboxs.addButton(self.checkbox_hide)

        vbox = QVBoxLayout()
        vbox.addWidget(self.table)
        vbox.addLayout(grid)

        if 0:
            vbox.addWidget(self.checkbox_show)
            vbox.addWidget(self.checkbox_hide)
        else:
            vbox1 = QVBoxLayout()
            vbox1.addWidget(self.checkbox_show)
            vbox1.addWidget(self.checkbox_hide)
            vbox.addLayout(vbox1)

        vbox.addStretch()
        #vbox.addWidget(self.check_apply)
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        self.opacity_edit.valueChanged.connect(self.on_opacity)  # clicked?
        self.line_width_edit.valueChanged.connect(
            self.on_line_width)  # clicked?
        self.point_size_edit.valueChanged.connect(
            self.on_point_size)  # clicked?
        self.color_edit.clicked.connect(self.on_color)
        self.checkbox_show.clicked.connect(self.on_show)
        self.checkbox_hide.clicked.connect(self.on_hide)
        #self.opacity_edit.clicked.connect(self.on_opacity)

        #self.connect(self.opacity_edit, QtCore.SIGNAL('clicked()'), self.on_opacity)
        #self.connect(self.line_width, QtCore.SIGNAL('clicked()'), self.on_line_width)
        #self.connect(self.point_size, QtCore.SIGNAL('clicked()'), self.on_point_size)
        #self.connect(self.color_edit, QtCore.SIGNAL('clicked()'), self.on_color)
        #self.connect(self.checkbox_show, QtCore.SIGNAL('clicked()'), self.on_show)
        #self.connect(self.checkbox_hide, QtCore.SIGNAL('clicked()'), self.on_hide)
        #self.connect(self.check_apply, QtCore.SIGNAL('clicked()'), self.on_check_apply)

        self.apply_button.clicked.connect(self.on_apply)
        self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)

        #self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
        #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
        #self.connect(self.cancel_button, QtCore.SIGNAL('clicked()'), self.on_cancel)
        #self.connect(self, QtCore.SIGNAL('triggered()'), self.closeEvent)

    def keyPressEvent(self, event):
        if event.key() == QtCore.Qt.Key_Escape:
            self.close()

    def closeEvent(self, event):
        self.out_data['close'] = True
        event.accept()

    def on_color(self):
        name = self.active_key
        obj = self.out_data[name]
        rgb_color_ints = obj.color

        msg = name
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    "Choose a %s color" % msg)
        if col.isValid():
            color = col.getRgbF()[:3]
            obj.color = color
            #print('new_color =', color)
            self.color_edit.setStyleSheet(
                "QPushButton {"
                "background-color: rgb(%s, %s, %s);" % tuple(obj.color) +
                #"border:1px solid rgb(255, 170, 255); "
                "}")

    def on_show(self):
        name = self.active_key
        is_checked = self.checkbox_show.isChecked()
        self.out_data[name].is_visible = is_checked

    def on_hide(self):
        name = self.active_key
        is_checked = self.checkbox_hide.isChecked()
        self.out_data[name].is_visible = not is_checked

    def on_line_width(self):
        name = self.active_key
        line_width = self.line_width_edit.value()
        self.out_data[name].line_width = line_width

    def on_point_size(self):
        name = self.active_key
        point_size = self.point_size_edit.value()
        self.out_data[name].point_size = point_size

    def on_opacity(self):
        name = self.active_key
        opacity = self.opacity_edit.value()
        self.out_data[name].opacity = opacity

    #def on_axis(self, text):
    ##print(self.combo_axis.itemText())
    #self._axis = str(text)
    #self.plane.setText('Point on %s? Plane:' % self._axis)
    #self.point_a.setText('Point on %s Axis:' % self._axis)
    #self.point_b.setText('Point on %s%s Plane:' % (self._axis, self._plane))

    #def on_plane(self, text):
    #self._plane = str(text)
    #self.point_b.setText('Point on %s%s Plane:' % (self._axis, self._plane))

    def on_check_apply(self):
        is_checked = self.check_apply.isChecked()
        self.apply_button.setDisabled(is_checked)

    def _on_float(self, field):
        try:
            eval_float_from_string(field.text())
            field.setStyleSheet("QLineEdit{background: white;}")
        except ValueError:
            field.setStyleSheet("QLineEdit{background: red;}")

    #def on_default_name(self):
    #self.name_edit.setText(str(self._default_name))
    #self.name_edit.setStyleSheet("QLineEdit{background: white;}")

    #def check_name(self, cell):
    #text = str(cell.text()).strip()
    #if len(text):
    #cell.setStyleSheet("QLineEdit{background: white;}")
    #return text, True
    #else:
    #cell.setStyleSheet("QLineEdit{background: red;}")
    #return None, False

    def on_validate(self):
        self.out_data['clicked_ok'] = True
        self.out_data['clicked_cancel'] = False

        old_obj = self.out_data[self.active_key]
        old_obj.line_width = self.line_width_edit.value()
        old_obj.point_size = self.point_size_edit.value()
        old_obj.opacity = self.opacity_edit.value()
        old_obj.is_visible = self.checkbox_show.isChecked()
        return True
        #name_value, flag0 = self.check_name(self.name_edit)
        #ox_value, flag1 = check_float(self.transparency_edit)
        #if flag0 and flag1:
        #self.out_data['clicked_ok'] = True
        #return True
        #return False

    def on_apply(self):
        passed = self.on_validate()
        if passed:
            self.win_parent.on_update_geometry_properties(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.out_data['clicked_ok'] = False
        self.out_data['clicked_cancel'] = True
        self.close()
Beispiel #15
0
class AlgorithmOptions(QWidget):
    def __init__(self, settings: StackSettings, image_view: StackImageView):
        super().__init__()
        self.settings = settings
        self.view_name = image_view.name
        self.show_result = QEnumComboBox(
            enum_class=LabelEnum)  # QCheckBox("Show result")
        self._set_show_label_from_settings()
        self.opacity = QDoubleSpinBox()
        self.opacity.setRange(0, 1)
        self.opacity.setSingleStep(0.1)
        self._set_opacity_from_settings()
        self.only_borders = QCheckBox("Only borders")
        self._set_border_mode_from_settings()
        self.borders_thick = QSpinBox()
        self.borders_thick.setRange(1, 25)
        self.borders_thick.setSingleStep(1)
        self._set_border_thick_from_settings()
        self.execute_in_background_btn = QPushButton("Execute in background")
        self.execute_in_background_btn.setToolTip(
            "Run calculation in background. Put result in multiple files panel"
        )
        self.execute_btn = QPushButton("Execute")
        self.execute_btn.setStyleSheet("QPushButton{font-weight: bold;}")
        self.execute_all_btn = QPushButton("Execute all")
        self.execute_all_btn.setToolTip(
            "Execute in batch mode segmentation with current parameter. File list need to be specified in image tab."
        )
        self.execute_all_btn.setDisabled(True)
        self.save_parameters_btn = QPushButton("Save parameters")
        self.block_execute_all_btn = False
        self.algorithm_choose_widget = AlgorithmChoose(settings,
                                                       mask_algorithm_dict)
        self.algorithm_choose_widget.result.connect(self.execution_result_set)
        self.algorithm_choose_widget.finished.connect(self.execution_finished)
        self.algorithm_choose_widget.progress_signal.connect(
            self.progress_info)

        # self.stack_layout = QStackedLayout()
        self.keep_chosen_components_chk = QCheckBox("Save selected components")
        self.keep_chosen_components_chk.setToolTip(
            "Save chosen components when loading segmentation form file\n or from multiple file widget."
        )
        self.keep_chosen_components_chk.stateChanged.connect(
            self.set_keep_chosen_components)
        self.keep_chosen_components_chk.setChecked(
            settings.keep_chosen_components)
        self.show_parameters = QPushButton("Show parameters")
        self.show_parameters.setToolTip(
            "Show parameters of segmentation for each components")
        self.show_parameters_widget = SegmentationInfoDialog(
            self.settings, self.algorithm_choose_widget.change_algorithm)
        self.show_parameters.clicked.connect(self.show_parameters_widget.show)
        self.choose_components = ChosenComponents()
        self.choose_components.check_change_signal.connect(
            image_view.refresh_selected)
        self.choose_components.mouse_leave.connect(image_view.component_unmark)
        self.choose_components.mouse_enter.connect(image_view.component_mark)
        # WARNING works only with one channels algorithms
        # SynchronizeValues.add_synchronization("channels_chose", widgets_list)
        self.chosen_list = []
        self.progress_bar2 = QProgressBar()
        self.progress_bar2.setHidden(True)
        self.progress_bar = QProgressBar()
        self.progress_bar.setHidden(True)
        self.progress_info_lab = QLabel()
        self.progress_info_lab.setHidden(True)
        self.file_list = []
        self.batch_process = BatchProceed()
        self.batch_process.progress_signal.connect(self.progress_info)
        self.batch_process.error_signal.connect(self.execution_all_error)
        self.batch_process.execution_done.connect(self.execution_all_done)
        self.batch_process.range_signal.connect(self.progress_bar.setRange)
        self.is_batch_process = False

        self.setContentsMargins(0, 0, 0, 0)
        main_layout = QVBoxLayout()
        # main_layout.setSpacing(0)
        opt_layout = QHBoxLayout()
        opt_layout.setContentsMargins(0, 0, 0, 0)
        opt_layout.addWidget(self.show_result)
        opt_layout.addWidget(right_label("Opacity:"))
        opt_layout.addWidget(self.opacity)
        main_layout.addLayout(opt_layout)
        opt_layout2 = QHBoxLayout()
        opt_layout2.setContentsMargins(0, 0, 0, 0)
        opt_layout2.addWidget(self.only_borders)
        opt_layout2.addWidget(right_label("Border thick:"))
        opt_layout2.addWidget(self.borders_thick)
        main_layout.addLayout(opt_layout2)
        btn_layout = QGridLayout()
        btn_layout.setContentsMargins(0, 0, 0, 0)
        btn_layout.addWidget(self.execute_btn, 0, 0)
        btn_layout.addWidget(self.execute_in_background_btn, 0, 1)
        btn_layout.addWidget(self.execute_all_btn, 1, 0)
        btn_layout.addWidget(self.save_parameters_btn, 1, 1)
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.progress_bar2)
        main_layout.addWidget(self.progress_bar)
        main_layout.addWidget(self.progress_info_lab)
        main_layout.addWidget(self.algorithm_choose_widget, 1)
        # main_layout.addWidget(self.algorithm_choose)
        # main_layout.addLayout(self.stack_layout, 1)
        main_layout.addWidget(self.choose_components)
        down_layout = QHBoxLayout()
        down_layout.addWidget(self.keep_chosen_components_chk)
        down_layout.addWidget(self.show_parameters)
        main_layout.addLayout(down_layout)
        main_layout.addStretch()
        main_layout.setContentsMargins(0, 0, 0, 0)
        # main_layout.setSpacing(0)
        self.setLayout(main_layout)

        # noinspection PyUnresolvedReferences
        self.execute_in_background_btn.clicked.connect(
            self.execute_in_background)
        self.execute_btn.clicked.connect(self.execute_action)
        self.execute_all_btn.clicked.connect(self.execute_all_action)
        self.save_parameters_btn.clicked.connect(self.save_parameters)
        # noinspection PyUnresolvedReferences
        self.opacity.valueChanged.connect(self._set_opacity)
        # noinspection PyUnresolvedReferences
        self.show_result.currentEnumChanged.connect(self._set_show_label)
        self.only_borders.stateChanged.connect(self._set_border_mode)
        # noinspection PyUnresolvedReferences
        self.borders_thick.valueChanged.connect(self._set_border_thick)
        image_view.component_clicked.connect(
            self.choose_components.other_component_choose)
        settings.chosen_components_widget = self.choose_components
        settings.components_change_list.connect(
            self.choose_components.new_choose)
        settings.image_changed.connect(
            self.choose_components.remove_components)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.only_border",
            self._set_border_mode_from_settings)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.border_thick",
            self._set_border_thick_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.opacity",
                                    self._set_opacity_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.show_label",
                                    self._set_show_label_from_settings)

    def _set_border_mode(self, value: bool):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.only_border", value)

    def _set_border_thick(self, value: int):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.border_thick", value)

    def _set_opacity(self, value: float):
        self.settings.set_in_profile(f"{self.view_name}.image_state.opacity",
                                     value)

    def _set_show_label(self, value: LabelEnum):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.show_label", value)

    def _set_border_mode_from_settings(self):
        self.only_borders.setChecked(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.only_border", True))

    def _set_border_thick_from_settings(self):
        self.borders_thick.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.border_thick", 1))

    def _set_opacity_from_settings(self):
        self.opacity.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.opacity", 1.0))

    def _set_show_label_from_settings(self):
        self.show_result.setCurrentEnum(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.show_label",
                LabelEnum.Show_results))

    @Slot(int)
    def set_keep_chosen_components(self, val):
        self.settings.set_keep_chosen_components(val)

    def save_parameters(self):
        dial = PSaveDialog(io_functions.save_parameters_dict,
                           system_widget=False,
                           settings=self.settings,
                           path=IO_SAVE_DIRECTORY)
        if not dial.exec_():
            return
        res = dial.get_result()
        res.save_class.save(res.save_destination,
                            self.algorithm_choose_widget.current_parameters())

    def file_list_change(self, val):
        self.file_list = val
        if len(self.file_list) > 0 and not self.block_execute_all_btn:
            self.execute_all_btn.setEnabled(True)
        else:
            self.execute_all_btn.setDisabled(True)

    def get_chosen_components(self):
        return sorted(self.choose_components.get_chosen())

    @property
    def segmentation(self):
        return self.settings.roi

    @segmentation.setter
    def segmentation(self, val):
        self.settings.roi = val

    def _image_changed(self):
        self.settings.roi = None
        self.choose_components.set_chose([], [])

    def _execute_in_background_init(self):
        if self.batch_process.isRunning():
            return
        self.progress_bar2.setVisible(True)
        self.progress_bar2.setRange(0, self.batch_process.queue.qsize())
        self.progress_bar2.setValue(self.batch_process.index)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.execute_btn.setDisabled(True)
        self.batch_process.start()

    def execute_in_background(self):
        # TODO check if components are properly passed
        widget = self.algorithm_choose_widget.current_widget()
        segmentation_profile = widget.get_segmentation_profile()
        task = BatchTask(self.settings.get_project_info(),
                         segmentation_profile, None)
        self.batch_process.add_task(task)
        self.progress_bar2.setRange(0, self.progress_bar2.maximum() + 1)
        self._execute_in_background_init()

    def execute_all_action(self):
        dial = PSaveDialog(
            SaveROI,
            settings=self.settings,
            system_widget=False,
            path="io.save_batch",
            file_mode=PSaveDialog.Directory,
        )
        if not dial.exec_():
            return
        folder_path = str(dial.selectedFiles()[0])

        widget = self.algorithm_choose_widget.current_widget()

        save_parameters = dial.values
        segmentation_profile = widget.get_segmentation_profile()
        for file_path in self.file_list:
            task = BatchTask(file_path, segmentation_profile,
                             (folder_path, save_parameters))
            self.batch_process.add_task(task)
        self.progress_bar2.setRange(
            0,
            self.progress_bar2.maximum() + len(self.file_list))
        self._execute_in_background_init()

    def execution_all_error(self, text):
        QMessageBox.warning(self, "Proceed error", text)

    def execution_all_done(self):
        if not self.batch_process.queue.empty():
            self._execute_in_background_init()
            return
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_bar2.setHidden(True)
        self.progress_info_lab.setHidden(True)

    def execute_action(self):
        self.execute_btn.setDisabled(True)
        self.execute_all_btn.setDisabled(True)
        self.block_execute_all_btn = True
        self.is_batch_process = False
        self.progress_bar.setRange(0, 0)
        self.choose_components.setDisabled(True)
        chosen = sorted(self.choose_components.get_chosen())
        blank = get_mask(self.settings.roi, self.settings.mask, chosen)
        if blank is not None:
            # Problem with handling time data in algorithms
            # TODO Fix This
            blank = blank[0]
        self.progress_bar.setHidden(False)
        widget: AlgorithmSettingsWidget = self.algorithm_choose_widget.current_widget(
        )
        widget.set_mask(blank)
        self.progress_bar.setRange(0, widget.algorithm.get_steps_num())
        widget.execute()
        self.chosen_list = chosen

    def progress_info(self, text, num, file_name="", file_num=0):
        self.progress_info_lab.setVisible(True)
        if file_name != "":
            self.progress_info_lab.setText(file_name + "\n" + text)
        else:
            self.progress_info_lab.setText(text)
        self.progress_bar.setValue(num)
        self.progress_bar2.setValue(file_num)

    def execution_finished(self):
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_info_lab.setHidden(True)
        self.choose_components.setDisabled(False)

    def execution_result_set(self, result):
        self.settings.set_segmentation_result(result)

    def showEvent(self, _):
        widget = self.algorithm_choose_widget.current_widget()
        widget.image_changed(self.settings.image)
Beispiel #16
0
class Dimension(QWidget):
    stateChanged = Signal(int)
    valueChanged = Signal()
    """
    pass in dimension

    state: one of (State.X, State.Y, State.NONE, State.DISBALE)

    Can be run independently by:

    from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension
    from qtpy.QtWidgets import QApplication
    app = QApplication([])
    window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'})
    window.show()
    app.exec_()
    """
    def __init__(self, dim_info, number=0, state=State.NONE, parent=None):
        super(Dimension, self).__init__(parent)

        self.minimum = dim_info['minimum']
        self.nbins = dim_info['number_of_bins']
        self.width = dim_info['width']
        self.number = number

        self.layout = QHBoxLayout(self)

        self.name = QLabel(dim_info['name'])
        self.units = QLabel(dim_info['units'])

        self.x = QPushButton('X')
        self.x.setFixedSize(32,32)
        self.x.setCheckable(True)
        self.x.clicked.connect(self.x_clicked)

        self.y = QPushButton('Y')
        self.y.setFixedSize(32,32)
        self.y.setCheckable(True)
        self.y.clicked.connect(self.y_clicked)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.nbins-1)
        self.slider.valueChanged.connect(self.slider_changed)

        self.spinbox = QDoubleSpinBox()
        self.spinbox.setDecimals(3)
        self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins-1))
        self.spinbox.setSingleStep(self.width)
        self.spinbox.valueChanged.connect(self.spinbox_changed)

        self.layout.addWidget(self.name)
        self.layout.addWidget(self.x)
        self.layout.addWidget(self.y)
        self.layout.addWidget(self.slider, stretch=1)
        self.layout.addStretch(0)
        self.layout.addWidget(self.spinbox)
        self.layout.addWidget(self.units)

        self.set_value(0)

        if self.nbins < 2:
            state = State.DISABLE

        self.set_state(state)

    def set_state(self, state):
        self.state = state
        if self.state == State.X:
            self.x.setChecked(True)
            self.y.setChecked(False)
            self.slider.hide()
            self.spinbox.hide()
            self.units.hide()
        elif self.state == State.Y:
            self.x.setChecked(False)
            self.y.setChecked(True)
            self.slider.hide()
            self.spinbox.hide()
            self.units.hide()
        elif self.state == State.NONE:
            self.x.setChecked(False)
            self.y.setChecked(False)
            self.slider.show()
            self.spinbox.show()
            self.units.show()
        else:
            self.x.setChecked(False)
            self.x.setDisabled(True)
            self.y.setChecked(False)
            self.y.setDisabled(True)
            self.slider.hide()
            self.spinbox.show()
            self.spinbox.setDisabled(True)
            self.units.show()

    def get_state(self):
        return self.state

    def x_clicked(self):
        old_state = self.state
        self.set_state(State.X)
        if self.state != old_state:
            self.stateChanged.emit(self.number)

    def y_clicked(self):
        old_state = self.state
        self.set_state(State.Y)
        if self.state != old_state:
            self.stateChanged.emit(self.number)

    def spinbox_changed(self):
        self.value = self.spinbox.value()
        self.update_slider()
        self.valueChanged.emit()

    def slider_changed(self):
        self.value = self.get_bin_center(self.slider.value())
        self.update_spinbox()
        self.valueChanged.emit()

    def get_bin_center(self, n):
        return (n+0.5)*self.width+self.minimum

    def update_slider(self):
        i = (self.value-self.minimum)/self.width
        self.slider.setValue(int(min(max(i, 0), self.nbins-1)))

    def update_spinbox(self):
        self.spinbox.setValue(self.value)

    def set_value(self, value):
        self.value = value
        self.update_slider()
        self.update_spinbox()

    def get_value(self):
        return self.value
Beispiel #17
0
class Dimension(QWidget):
    stateChanged = Signal(int)
    valueChanged = Signal()
    """
    pass in dimension

    state: one of (State.X, State.Y, State.NONE, State.DISABLE)

    Can be run independently by:

    from mantidqt.widgets.sliceviewer.dimensionwidget import Dimension
    from qtpy.QtWidgets import QApplication
    app = QApplication([])
    window = Dimension({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'})
    window.show()
    app.exec_()
    """

    def __init__(self, dim_info, number=0, state=State.NONE, parent=None):
        super().__init__(parent)

        self.minimum = dim_info['minimum']
        self.nbins = dim_info['number_of_bins']
        self.width = dim_info['width']
        self.number = number

        self.layout = QHBoxLayout(self)
        self.layout.setContentsMargins(0, 2, 0, 0)

        self.name = QLabel(dim_info['name'])
        self.units = QLabel(dim_info['units'])

        self.x = QPushButton('X')
        self.x.setCheckable(True)
        self.x.clicked.connect(self.x_clicked)
        # square button based on height. Default sizeHint is too large
        self.x.setFixedWidth(self.x.sizeHint().height())

        self.y = QPushButton('Y')
        self.y.setCheckable(True)
        self.y.clicked.connect(self.y_clicked)
        self.y.setFixedWidth(self.y.sizeHint().height())

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.nbins - 1)
        self.slider.valueChanged.connect(self.slider_changed)

        self.spinbox = QDoubleSpinBox()
        self.spinbox.setDecimals(3)
        self.spinbox.setRange(self.get_bin_center(0), self.get_bin_center(self.nbins - 1))
        self.spinbox.setSingleStep(self.width)
        self.spinbox.editingFinished.connect(self.spinbox_changed)

        self.layout.addWidget(self.name)
        self.button_layout = QHBoxLayout()
        self.button_layout.setContentsMargins(0, 0, 0, 0)
        self.button_layout.setSpacing(0)
        self.button_layout.addWidget(self.x)
        self.button_layout.addWidget(self.y)
        self.layout.addLayout(self.button_layout)
        self.layout.addWidget(self.slider, stretch=1)
        self.layout.addStretch(0)
        self.layout.addWidget(self.spinbox)
        self.layout.addWidget(self.units)

        self.set_value(0)

        if self.nbins < 2:
            state = State.DISABLE

        self.set_state(state)

    def set_state(self, state):
        self.state = state
        if self.state == State.X:
            self.x.setChecked(True)
            self.y.setChecked(False)
            self.slider.hide()
            self.spinbox.hide()
            self.units.hide()
        elif self.state == State.Y:
            self.x.setChecked(False)
            self.y.setChecked(True)
            self.slider.hide()
            self.spinbox.hide()
            self.units.hide()
        elif self.state == State.NONE:
            self.x.setChecked(False)
            self.y.setChecked(False)
            self.slider.show()
            self.spinbox.show()
            self.units.show()
        else:
            self.x.setChecked(False)
            self.x.setDisabled(True)
            self.y.setChecked(False)
            self.y.setDisabled(True)
            self.slider.hide()
            self.spinbox.show()
            self.spinbox.setDisabled(True)
            self.units.show()

    def get_state(self):
        return self.state

    def x_clicked(self):
        old_state = self.state
        self.set_state(State.X)
        if self.state != old_state:
            self.stateChanged.emit(self.number)

    def y_clicked(self):
        old_state = self.state
        self.set_state(State.Y)
        if self.state != old_state:
            self.stateChanged.emit(self.number)

    def spinbox_changed(self):
        self.value = self.spinbox.value()
        self.update_slider()

    def slider_changed(self):
        self.value = self.get_bin_center(self.slider.value())
        self.update_spinbox()
        self.valueChanged.emit()

    def get_bin_center(self, n):
        return (n + 0.5) * self.width + self.minimum

    def update_slider(self):
        i = (self.value - self.minimum) / self.width
        self.slider.setValue(int(min(max(i, 0), self.nbins - 1)))

    def update_spinbox(self):
        self.spinbox.setValue(self.value)

    def set_value(self, value):
        self.value = value
        self.update_slider()
        self.update_spinbox()

    def get_value(self):
        return self.value
Beispiel #18
0
class DimensionMDE(Dimension):
    binningChanged = Signal()
    """
    MDEventWorkspace has additional properties for either number_of_bins or thickness

    from mantidqt.widgets.sliceviewer.dimensionwidget import DimensionMDE
    from qtpy.QtWidgets import QApplication
    app = QApplication([])
    window = DimensionMDE({'minimum':-1.1, 'number_of_bins':11, 'width':0.2, 'name':'Dim0', 'units':'A'})
    window.show()
    app.exec_()
    """
    def __init__(self, dim_info, number=0, state=State.NONE, parent=None):

        # hack in a number_of_bins for MDEventWorkspace
        dim_info['number_of_bins'] = 1000
        dim_info['width'] = (dim_info['maximum']-dim_info['minimum'])/1000

        self.spinBins = QSpinBox()
        self.spinBins.setRange(2,9999)
        self.spinBins.setValue(100)
        self.spinBins.hide()
        self.spinBins.setMinimumWidth(110)
        self.spinThick = QDoubleSpinBox()
        self.spinThick.setRange(0.001,999)
        self.spinThick.setValue(0.1)
        self.spinThick.setSingleStep(0.1)
        self.spinThick.setDecimals(3)
        self.spinThick.setMinimumWidth(110)
        self.rebinLabel = QLabel("thick")
        self.rebinLabel.setMinimumWidth(44)

        super(DimensionMDE, self).__init__(dim_info, number, state, parent)

        self.spinBins.valueChanged.connect(self.binningChanged)
        self.spinThick.valueChanged.connect(self.valueChanged)

        self.layout.addWidget(self.spinBins)
        self.layout.addWidget(self.spinThick)
        self.layout.addWidget(self.rebinLabel)

    def get_bins(self):
        return int(self.spinBins.value())

    def get_thickness(self):
        return float(self.spinThick.value())

    def set_state(self, state):
        super(DimensionMDE, self).set_state(state)
        if self.state == State.X:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.Y:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.NONE:
            self.spinBins.hide()
            self.spinThick.show()
            self.rebinLabel.setText('thick')
        else:
            self.spinBins.hide()
            self.spinThick.hide()
            self.rebinLabel.hide()
Beispiel #19
0
class AnimationWindow(PyDialog):
    """
    +-------------------+
    | Animation         |
    +-------------------------+
    | icase   ______          |
    | scale   ______  Default |
    | time    ______  Default |
    |                         |
    | nframes ______  Default |
    | resolu. ______  Default |
    | Dir     ______  Browse  |
    | iFrame  ______          |
    |                         |
    | Animations:             |
    | o Scale, Phase, Time    |  # TODO: add time
    |                         |
    | x delete images         |
    | x repeat                |  # TODO: change to an integer
    | x make gif              |
    |                         |
    |      Step, RunAll       |
    |         Close           |
    +-------------------------+

    TODO: add key-frame support
    """
    def __init__(self, data, win_parent=None):
        PyDialog.__init__(self, data, win_parent)
        self.set_font_size(data['font_size'])
        self.istep = 0
        self._animate_type = 'time'

        self._updated_animation = False
        self._active_deformation = 0.
        self._icase = data['icase']
        self._default_name = data['name']
        self._default_time = data['time']
        self._default_fps = data['frames/sec']
        self._default_resolution = data['resolution']

        self._scale = data['scale']
        self._default_scale = data['default_scale']
        self._default_is_scale = data['is_scale']

        self._phase = data['phase']
        self._default_phase = data['default_phase']

        self._default_dirname = data['dirname']
        self._default_gif_name = os.path.join(self._default_dirname,
                                              data['name'] + '.gif')

        self.animation_types = [
            'Animate Scale',
        ]
        #'Animate Phase',
        #'Animate Time',
        #'Animate Frequency Sweep'
        #]

        self.setWindowTitle('Animate Model')
        self.create_widgets()
        self.create_layout()
        self.set_connections()

        self.is_gui = False
        if hasattr(self.win_parent, '_updated_legend'):
            self.win_parent.is_animate_open = True
            self.is_gui = True

    def create_widgets(self):
        """creates the menu objects"""
        icase_max = 1000  # TODO: update 1000

        self.icase = QLabel("iCase:")
        self.icase_edit = QSpinBox(self)
        self.icase_edit.setRange(1, icase_max)
        self.icase_edit.setSingleStep(1)
        self.icase_edit.setValue(self._icase)
        self.icase_edit.setToolTip(
            'Case Number for the Scale/Phase Animation Type.\n'
            'Defaults to the result you had shown when you clicked "Create Animation".\n'
            'iCase can be seen by clicking "Apply" on a result.')

        self.scale = QLabel("Scale:")
        self.scale_edit = QLineEdit(str(self._scale))
        self.scale_button = QPushButton("Default")
        self.scale_edit.setToolTip('Scale factor of the "deflection"')
        self.scale_button.setToolTip('Sets the scale factor of the gif to %s' %
                                     self._scale)

        self.time = QLabel("Total Time (sec):")
        self.time_edit = QDoubleSpinBox(self)
        self.time_edit.setValue(self._default_time)
        self.time_edit.setRange(0.1, 10.0)
        self.time_edit.setDecimals(2)
        self.time_edit.setSingleStep(0.1)
        self.time_button = QPushButton("Default")
        self.time_edit.setToolTip("Total time of the gif")
        self.time_button.setToolTip('Sets the total time of the gif to %.2f' %
                                    self._default_time)

        self.fps = QLabel("Frames/Second:")
        self.fps_edit = QSpinBox(self)
        self.fps_edit.setRange(1, 60)
        self.fps_edit.setSingleStep(1)
        self.fps_edit.setValue(self._default_fps)
        self.fps_button = QPushButton("Default")
        self.fps_edit.setToolTip(
            "A higher FPS is smoother, but may not play well for large gifs")
        self.fps_button.setToolTip('Sets the FPS to %s' % self._default_fps)

        self.resolution = QLabel("Resolution Scale:")
        self.resolution_edit = QSpinBox(self)
        self.resolution_edit.setRange(1, 5)
        self.resolution_edit.setSingleStep(1)
        self.resolution_edit.setValue(self._default_resolution)
        self.resolution_button = QPushButton("Default")
        self.resolution_edit.setToolTip(
            'Scales the window resolution by an integer factor')
        self.resolution_button.setToolTip('Sets the resolution to %s' %
                                          self._default_resolution)

        #-----------------
        # Time plot
        self.icase_start = QLabel("iCase Start:")
        self.icase_start_edit = QSpinBox(self)
        self.icase_start_edit.setRange(0, icase_max)
        self.icase_start_edit.setSingleStep(1)
        self.icase_start_edit.setValue(self._icase)
        self.icase_start_button = QPushButton("Default")

        self.icase_end = QLabel("iCase End:")
        self.icase_end_edit = QSpinBox(self)
        self.icase_end_edit.setRange(0, icase_max)
        self.icase_end_edit.setSingleStep(1)
        self.icase_end_edit.setValue(self._icase)
        self.icase_end_button = QPushButton("Default")

        self.icase_delta = QLabel("iCase Delta:")
        self.icase_delta_edit = QSpinBox(self)
        self.icase_delta_edit.setRange(1, icase_max)
        self.icase_delta_edit.setSingleStep(1)
        self.icase_delta_edit.setValue(1)
        self.icase_delta_button = QPushButton("Default")

        self.min_value = QLabel("Min Value:")
        self.min_value_edit = QLineEdit(str(0.))
        #self.min_value_edit.setRange(1, 1000)
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.min_value_button = QPushButton("Default")

        self.max_value = QLabel("Max Value:")
        self.max_value_edit = QLineEdit(str(1.))
        #self.min_value_edit.setRange(1, 1000)  # TODO: update 1000
        #self.min_value_edit.setSingleStep(1)
        #self.min_value_edit.setValue(1)
        self.max_value_button = QPushButton("Default")

        self.icase_start_edit.setToolTip('The first frame of the animation')
        self.icase_end_edit.setToolTip(
            'The last frame of the animation\n'
            'Assumes icase_start + nframes * icase_delta = icase_end')
        self.icase_delta_edit.setToolTip(
            'The frame step size (to skip non-consecutive results).\n'
            'Frame skipping can be used to:\n'
            "  - skip across results that you don't want to plot\n"
            '  - adjust the FPS')

        self.min_value_edit.setToolTip(
            'Min value of the legend (not supported)')
        self.max_value_edit.setToolTip(
            'Max value of the legend (not supported)')
        #'time' : 0.,
        #'default_time' : 0,
        #'icase_start' : 10,
        #'icase_delta' : 3,
        #'min_value' : 0.,
        #'max_value' : 1000.,

        self.browse_folder = QLabel('Output Directory:')
        self.browse_folder_edit = QLineEdit(str(self._default_dirname))
        self.browse_folder_button = QPushButton('Browse')
        self.browse_folder_edit.setToolTip(
            'Location to save the png/gif files')

        self.gif = QLabel("Gif Filename:")
        self.gif_edit = QLineEdit(str(self._default_name + '.gif'))
        self.gif_button = QPushButton('Default')
        self.gif_edit.setToolTip('Name of the gif')
        self.gif_button.setToolTip('Sets the name of the gif to %s.gif' %
                                   self._default_name)

        # scale / phase
        self.animate_scale_radio = QRadioButton("Animate Scale")
        self.animate_phase_radio = QRadioButton("Animate Phase")
        self.animate_time_radio = QRadioButton("Animate Time")
        self.animate_freq_sweeep_radio = QRadioButton(
            "Animate Frequency Sweep")
        self.animate_scale_radio.setToolTip(
            'Animates the scale factor based on the "Animation Type"')
        self.animate_time_radio.setToolTip('Animates the time/load/mode step')

        self.animate_scale_radio.setChecked(self._default_is_scale)
        self.animate_phase_radio.setChecked(not self._default_is_scale)
        self.animate_time_radio.setChecked(False)

        msg = 'Scale : Animates the scale factor based on the "Animation Profile"\n'
        if self._default_phase is None:
            self.animate_phase_radio.setDisabled(True)
            self.animate_phase_radio.setToolTip('Animates the phase angle '
                                                '(only for complex results)')
            msg += 'Phase : Animates the phase angle (only for complex results)\n'
        else:
            self.animate_phase_radio.setToolTip("Animates the phase angle")
            msg += 'Phase : Animates the phase angle\n'
        msg += (
            'Time : Animates the time/load/mode step\n'
            'Freq Sweep : Animates a complex result across a range of frequencies '
            '(not supported)\n')

        self.animate_freq_sweeep_radio.setDisabled(True)
        self.animate_freq_sweeep_radio.setToolTip(
            'Animates a complex result across a range of frequencies (not supported)'
        )
        self.animation_type = QLabel("Animation Type:")
        animation_type = OrderedDict()
        #scale_msg = 'Scale\n'
        #phase_msg = 'Phase\n'
        #time_msg = 'Time\n'
        #animation_types = [
        #('Animate Scale', scale_msg),
        #('Animate Phase', phase_msg),
        #('Animate Time', time_msg),
        ##'Animate Frequency Sweep'
        #]

        if self._phase is not None:
            self.animation_types.append('Animate Phase')
        self.animation_types.append('Animate Time')

        self.animation_profile = QLabel("Animation Profile:")

        self.animation_profile_edit = QComboBox()
        for animation_profile in ANIMATION_PROFILES:
            self.animation_profile_edit.addItem(animation_profile)
        self.animation_profile_edit.setToolTip('The profile for a scaled GIF')

        self.animation_type_edit = QComboBox()
        # TODO: add a tooltip for each item
        for animation_type in self.animation_types:
            self.animation_type_edit.addItem(animation_type)
        #self.animation_type_edit.setToolTip('The profile for a scaled GIF')
        self.animation_type_edit.setToolTip(msg)

        self.csv_profile = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_browse_button = QPushButton('Browse')
        self.csv_profile_edit.setToolTip(
            'The path to the CSV file of (Scale1, Scale2, Scale3, ...)')

        widget = QWidget(self)
        horizontal_vertical_group = QButtonGroup(widget)
        horizontal_vertical_group.addButton(self.animate_scale_radio)
        horizontal_vertical_group.addButton(self.animate_phase_radio)
        horizontal_vertical_group.addButton(self.animate_time_radio)
        horizontal_vertical_group.addButton(self.animate_freq_sweeep_radio)

        # one / two sided
        self.onesided_radio = QRadioButton("One Sided")
        self.onesided_radio.setToolTip(
            "A one sided gif doesn't return to the starting point (e.g., 0 to 360 degrees)"
        )
        self.twosided_radio = QRadioButton("Two Sided")
        self.twosided_radio.setToolTip(
            'A two sided gif returns to the starting point (e.g., 0 to 10 to 0)'
        )

        if self._default_phase is None:
            self.onesided_radio.setChecked(False)
            self.twosided_radio.setChecked(True)
        else:
            self.onesided_radio.setChecked(True)
            self.twosided_radio.setChecked(False)
        widget = QWidget(self)
        horizontal_vertical_group = QButtonGroup(widget)
        horizontal_vertical_group.addButton(self.onesided_radio)
        horizontal_vertical_group.addButton(self.twosided_radio)

        # animate in gui
        self.animate_in_gui_checkbox = QCheckBox("Animate In GUI?")
        self.animate_in_gui_checkbox.setChecked(True)

        # make images
        self.make_images_checkbox = QCheckBox("Make images?")
        self.make_images_checkbox.setChecked(True)

        # make images
        self.overwrite_images_checkbox = QCheckBox("Overwrite images?")
        self.overwrite_images_checkbox.setChecked(True)

        # delete images when finished
        self.delete_images_checkbox = QCheckBox("Delete images when finished?")
        self.delete_images_checkbox.setChecked(True)

        # endless loop
        self.repeat_checkbox = QCheckBox("Repeat?")
        self.repeat_checkbox.setChecked(True)
        self.repeat_checkbox.setToolTip(
            "Repeating creates an infinitely looping gif")

        # endless loop
        self.make_gif_checkbox = QCheckBox("Make Gif?")
        if IS_IMAGEIO:
            self.make_gif_checkbox.setChecked(True)
        else:
            self.make_gif_checkbox.setChecked(False)
            self.make_gif_checkbox.setEnabled(False)
            self.make_gif_checkbox.setToolTip(
                'imageio is not available; install it')

        # bottom buttons
        self.step_button = QPushButton("Step")
        self.wipe_button = QPushButton("Wipe Deformed Shape")
        self.stop_button = QPushButton("Stop")
        self.run_button = QPushButton("Run All")

        self.step_button.setToolTip(
            'Steps through the animation (for testing)')
        self.wipe_button.setToolTip(
            'Removes the existing "deflecton" from the animation')
        self.stop_button.setToolTip('Stops the animation')
        self.run_button.setToolTip('Creates the animation')

        self.wipe_button.setEnabled(False)
        #self.wipe_button.hide()
        self.stop_button.setEnabled(False)

        #self.apply_button = QPushButton("Apply")
        #self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Close")

        #self.set_grid_time(enabled=False)
        #self.set_grid_scale(enabled=self._default_is_scale)
        if self._default_phase:
            self.on_animate_phase(force=True)
        else:
            self.on_animate_scale(force=True)

    def set_connections(self):
        """creates button actions"""
        self.scale_button.clicked.connect(self.on_default_scale)
        self.time_button.clicked.connect(self.on_default_time)

        self.fps_button.clicked.connect(self.on_default_fps)
        self.resolution_button.clicked.connect(self.on_default_resolution)
        self.browse_folder_button.clicked.connect(self.on_browse_folder)
        self.csv_profile_browse_button.clicked.connect(self.on_browse_csv)
        self.gif_button.clicked.connect(self.on_default_name)

        self.step_button.clicked.connect(self.on_step)
        self.wipe_button.clicked.connect(self.on_wipe)
        self.stop_button.clicked.connect(self.on_stop)
        self.run_button.clicked.connect(self.on_run)

        #self.animate_scale_radio.clicked.connect(self.on_animate_scale)
        #self.animate_phase_radio.clicked.connect(self.on_animate_phase)
        #self.animate_time_radio.clicked.connect(self.on_animate_time)
        self.animation_type_edit.currentIndexChanged.connect(self.on_animate)
        #self.animate_freq_sweeep_radio

        #self.apply_button.clicked.connect(self.on_apply)
        #self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)

        self.animate_in_gui_checkbox.clicked.connect(self.on_animate_in_gui)
        self.animate_in_gui_checkbox.setChecked(True)
        self.on_animate_in_gui()

    def on_animate_in_gui(self):
        animate_in_gui = self.animate_in_gui_checkbox.isChecked()
        enable = not animate_in_gui
        self.make_images_checkbox.setEnabled(enable)
        self.delete_images_checkbox.setEnabled(enable)
        self.make_gif_checkbox.setEnabled(enable)
        self.repeat_checkbox.setEnabled(enable)
        self.resolution_button.setEnabled(enable)
        self.resolution_edit.setEnabled(enable)
        self.gif_edit.setEnabled(enable)
        self.gif_button.setEnabled(enable)
        self.browse_folder_button.setEnabled(enable)
        self.browse_folder_edit.setEnabled(enable)
        self.step_button.setEnabled(enable)
        #wipe_button

    def on_animate(self, value):
        """
        animate pulldown

        Parameters
        ----------
        value : int
            index in animation_types
        """
        #animation_types = ['Animate Scale', 'Animate Phase', 'Animate Time',
        #'Animate Frequency Sweep']
        animation_type = self.animation_types[value]
        if animation_type == 'Animate Scale':
            self.on_animate_scale()
        elif animation_type == 'Animate Phase':
            self.on_animate_phase()
        elif animation_type == 'Animate Time':
            self.on_animate_time()
        else:
            raise NotImplementedError('value = ', value)

    def on_animate_time(self, force=False):
        """enables the secondary input"""
        #print('on_animate_time')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'time')
        self.set_grid_time(True, 'time')
        self._animate_type = 'time'

    def on_animate_scale(self, force=False):
        """enables the secondary input"""
        #print('on_animate_scale')
        self.set_grid_scale(True, 'scale')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'scale')
        self._animate_type = 'scale'

    def on_animate_phase(self, force=False):
        """enables the secondary input"""
        #print('on_animate_phase')
        if self._animate_type == 'scale' or force:
            self.set_grid_scale(False, 'phase')
        if self._animate_type == 'time' or force:
            self.set_grid_time(False, 'phase')
        self._animate_type = 'phase'

    def set_grid_scale(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_scale; enabled = %r' % (word, enabled))
        self.animation_profile.setEnabled(enabled)
        self.animation_profile_edit.setEnabled(enabled)

        # TODO: doesn't work...
        #self.csv_profile.setEnabled(enabled)
        #self.csv_profile_edit.setEnabled(enabled)
        #self.csv_profile_button.setEnabled(enabled)

    def set_grid_time(self, enabled=True, word=''):
        """enables/disables the secondary input"""
        #print('%s-set_grid_time; enabled = %r' % (word, enabled))
        self.icase_start.setEnabled(enabled)
        self.icase_start_edit.setEnabled(enabled)
        self.icase_start_button.setEnabled(enabled)

        self.icase_end.setEnabled(enabled)
        self.icase_end_edit.setEnabled(enabled)
        self.icase_end_button.setEnabled(enabled)

        self.icase_delta.setEnabled(enabled)
        self.icase_delta_edit.setEnabled(enabled)
        self.icase_delta_button.setEnabled(enabled)

        self.min_value.setEnabled(enabled)
        self.min_value_edit.setEnabled(enabled)
        self.min_value_button.setEnabled(enabled)

        self.max_value.setEnabled(enabled)
        self.max_value_edit.setEnabled(enabled)
        self.max_value_button.setEnabled(enabled)

        self.icase.setEnabled(not enabled)
        self.icase_edit.setEnabled(not enabled)
        self.fps.setEnabled(not enabled)
        self.fps_edit.setEnabled(not enabled)
        self.fps_button.setEnabled(not enabled)

    def on_browse_folder(self):
        """opens a folder dialog"""
        dirname = open_directory_dialog(self, 'Select a Directory')
        if not dirname:
            return
        self.browse_folder_edit.setText(dirname)

    def on_browse_csv(self):
        """opens a file dialog"""
        default_filename = ''
        file_types = 'Delimited Text (*.txt; *.dat; *.csv)'
        dirname = open_file_dialog(self, 'Select a CSV File', default_filename,
                                   file_types)
        if not dirname:
            return
        self.csv_profile_browse_button.setText(dirname)

    def on_default_name(self):
        """sets the default gif name"""
        self.gif_edit.setText(self._default_name + '.gif')

    def on_default_scale(self):
        """sets the default displacement scale factor"""
        self.scale_edit.setText(str(self._default_scale))
        self.scale_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_time(self):
        """sets the default gif time"""
        self.time_edit.setValue(self._default_time)

    def on_default_fps(self):
        """sets the default FPS"""
        self.fps_edit.setValue(self._default_fps)

    def on_default_resolution(self):
        """sets the default image resolution scale factor"""
        self.resolution_edit.setValue(self._default_resolution)

    def create_layout(self):
        """displays the menu objects"""
        grid = QGridLayout()

        grid.addWidget(self.icase, 0, 0)
        grid.addWidget(self.icase_edit, 0, 1)

        grid.addWidget(self.scale, 1, 0)
        grid.addWidget(self.scale_edit, 1, 1)
        grid.addWidget(self.scale_button, 1, 2)

        grid.addWidget(self.time, 2, 0)
        grid.addWidget(self.time_edit, 2, 1)
        grid.addWidget(self.time_button, 2, 2)

        # spacer
        spacer = QLabel('')

        grid.addWidget(self.fps, 3, 0)
        grid.addWidget(self.fps_edit, 3, 1)
        grid.addWidget(self.fps_button, 3, 2)

        grid.addWidget(self.resolution, 4, 0)
        grid.addWidget(self.resolution_edit, 4, 1)
        grid.addWidget(self.resolution_button, 4, 2)

        grid.addWidget(self.browse_folder, 5, 0)
        grid.addWidget(self.browse_folder_edit, 5, 1)
        grid.addWidget(self.browse_folder_button, 5, 2)

        grid.addWidget(self.gif, 6, 0)
        grid.addWidget(self.gif_edit, 6, 1)
        grid.addWidget(self.gif_button, 6, 2)

        grid.addWidget(self.animation_type, 7, 0)
        grid.addWidget(self.animation_type_edit, 7, 1)

        grid.addWidget(spacer, 8, 0)

        #----------
        #Time
        grid_time = QGridLayout()
        grid_time.addWidget(self.icase_start, 0, 0)
        grid_time.addWidget(self.icase_start_edit, 0, 1)
        #grid_time.addWidget(self.icase_start_button, 0, 2)

        grid_time.addWidget(self.icase_end, 1, 0)
        grid_time.addWidget(self.icase_end_edit, 1, 1)
        #grid_time.addWidget(self.icase_end_button, 1, 2)

        grid_time.addWidget(self.icase_delta, 2, 0)
        grid_time.addWidget(self.icase_delta_edit, 2, 1)
        #grid_time.addWidget(self.icase_delta_button, 2, 2)

        #grid_time.addWidget(self.min_value, 3, 0)
        #grid_time.addWidget(self.min_value_edit, 3, 1)
        #grid_time.addWidget(self.min_value_button, 3, 2)

        #grid_time.addWidget(self.max_value, 4, 0)
        #grid_time.addWidget(self.max_value_edit, 4, 1)
        #grid_time.addWidget(self.max_value_button, 4, 2)
        grid_time.addWidget(spacer, 5, 0)

        #--------------
        grid_scale = QGridLayout()
        grid_scale.addWidget(self.animation_profile, 0, 0)
        grid_scale.addWidget(self.animation_profile_edit, 0, 1)

        #grid_scale.addWidget(self.csv_profile, 1, 0)
        #grid_scale.addWidget(self.csv_profile_edit, 1, 1)
        #grid_scale.addWidget(self.csv_profile_browse_button, 1, 2)

        self.csv_profile = QLabel("CSV profile:")
        self.csv_profile_edit = QLineEdit()
        self.csv_profile_button = QPushButton('Browse')

        #box_time = QVBoxLayout()
        # TODO: It's super annoying that the animate time box doesn't
        #       line up with the previous box
        box_scale = QGroupBox('Animate Scale')
        box_scale.setLayout(grid_scale)

        box_time = QGroupBox('Animate Time')
        box_time.setLayout(grid_time)
        #----------

        grid2 = QGridLayout()
        #grid2.addWidget(self.animate_scale_radio, 8, 0)
        #grid2.addWidget(self.animate_phase_radio, 8, 1)
        #grid2.addWidget(self.animate_time_radio, 8, 2)
        #grid2.addWidget(self.animate_freq_sweeep_radio, 8, 3)

        grid2.addWidget(self.animate_in_gui_checkbox, 10, 0)
        grid2.addWidget(self.make_images_checkbox, 11, 0)
        #grid2.addWidget(self.overwrite_images_checkbox, 11, 0)
        grid2.addWidget(self.delete_images_checkbox, 11, 1)
        grid2.addWidget(self.make_gif_checkbox, 11, 2)
        grid2.addWidget(self.repeat_checkbox, 12, 0)

        grid2.addWidget(spacer, 13, 0)
        grid_hbox = QHBoxLayout()
        grid_hbox.addWidget(spacer)
        grid_hbox.addLayout(grid2)
        grid_hbox.addWidget(spacer)

        # bottom buttons
        step_run_box = QHBoxLayout()
        step_run_box.addWidget(self.step_button)
        step_run_box.addWidget(self.wipe_button)
        step_run_box.addWidget(self.stop_button)
        step_run_box.addWidget(self.run_button)

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        vbox.addWidget(box_scale)
        vbox.addWidget(box_time)
        #vbox.addLayout(checkboxes)
        vbox.addLayout(grid_hbox)
        vbox.addStretch()
        vbox.addLayout(step_run_box)
        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def on_step(self):
        """click the Step button"""
        passed, validate_out = self.on_validate()
        if passed:
            try:
                self._make_gif(validate_out, istep=self.istep)
                self.istep += 1
            except IndexError:
                self._make_gif(validate_out, istep=0)
                self.istep += 1
            self.wipe_button.setEnabled(True)

    def on_wipe(self):
        """click the Wipe button"""
        passed, validate_out = self.on_validate(wipe=True)
        if passed:
            self.istep = 0
            self._make_gif(validate_out, istep=self.istep)
            self.wipe_button.setEnabled(False)
            self.stop_button.setEnabled(False)

    def on_stop(self):
        """click the Stop button"""
        #passed, validate_out = self.on_validate()
        #if passed:
        #self._make_gif(validate_out, stop_animation=True)
        if self.is_gui:
            self.win_parent.win_parent.stop_animation()

        self.wipe_button.setEnabled(True)
        self.stop_button.setEnabled(False)

    def on_run(self):
        """click the Run button"""
        self.istep = 0
        self.wipe_button.setEnabled(False)
        self.stop_button.setEnabled(True)

        passed, validate_out = self.on_validate()
        if passed:
            self._make_gif(validate_out, istep=None)
        return passed

    def _make_gif(self, validate_out, istep=None, stop_animation=False):
        """interface for making the gif"""
        icase, scale, time, fps, animate_in_gui, magnify, output_dir, gifbase = validate_out

        gif_filename = None
        if not stop_animation and not animate_in_gui and gifbase is not None:
            if gifbase.lower().endswith('.gif'):
                gifbase = gifbase[:-4]
            gif_filename = os.path.join(output_dir, gifbase + '.gif')

        animate_scale = self.animate_scale_radio.isChecked()
        animate_phase = self.animate_phase_radio.isChecked()
        animate_time = self.animate_time_radio.isChecked()

        animate_scale = False
        animate_phase = False
        animate_time = False
        if self._animate_type == 'scale':
            animate_scale = True
        elif self._animate_type == 'phase':
            animate_phase = True
        elif self._animate_type == 'time':
            animate_time = True
        else:
            raise NotImplementedError(self._animate_type)

        make_images = self.make_images_checkbox.isChecked()
        delete_images = self.delete_images_checkbox.isChecked()
        make_gif = self.make_gif_checkbox.isChecked()
        key = str(self.animation_profile_edit.currentText())
        #profile = ANIMATION_PROFILES[key]

        #ANIMATION_PROFILES['0 to Scale'] = [0., 1.]
        #ANIMATION_PROFILES['0 to Scale to 0'] = [0., 1., 0.]
        if key == '0 to Scale':
            onesided = True
        else:
            onesided = False

        icase_start = self.icase_start_edit.value()
        icase_end = self.icase_end_edit.value()
        icase_delta = self.icase_delta_edit.value()

        #onesided = self.onesided_radio.isChecked()
        bool_repeat = self.repeat_checkbox.isChecked(
        )  # TODO: change this to an integer
        if bool_repeat:
            nrepeat = 0
        else:
            nrepeat = 1
        #self.out_data['is_shown'] = self.show_radio.isChecked()
        #icase = self._icase
        if self.is_gui:
            self.win_parent.win_parent.make_gif(
                gif_filename,
                scale,
                istep=istep,
                animate_scale=animate_scale,
                animate_phase=animate_phase,
                animate_time=animate_time,
                icase=icase,
                icase_start=icase_start,
                icase_end=icase_end,
                icase_delta=icase_delta,
                time=time,
                onesided=onesided,
                nrepeat=nrepeat,
                fps=fps,
                magnify=magnify,
                make_images=make_images,
                delete_images=delete_images,
                make_gif=make_gif,
                stop_animation=stop_animation,
                animate_in_gui=animate_in_gui,
            )

        self.out_data['clicked_ok'] = True
        self.out_data['close'] = True

    def on_validate(self, wipe=False):
        """checks to see if the input is valid"""
        # requires no special validation
        icase, flag0 = self.check_int(self.icase_edit)
        scale, flag1 = self.check_float(self.scale_edit)
        time, flag2 = self.check_float(self.time_edit)
        fps, flag3 = self.check_float(self.fps_edit)
        if wipe:
            animate_in_gui = False
        else:
            animate_in_gui = self.animate_in_gui_checkbox.isChecked()

        if animate_in_gui or wipe:
            passed = all([flag0, flag1, flag2, flag3])
            magnify, output_dir, gifbase = None, None, None
        else:
            magnify, flag4 = self.check_int(self.resolution_edit)
            output_dir, flag5 = self.check_path(self.browse_folder_edit)
            gifbase, flag6 = self.check_name(self.gif_edit)
            passed = all([flag0, flag1, flag2, flag3, flag4, flag5, flag6])
        return passed, (icase, scale, time, fps, animate_in_gui, magnify,
                        output_dir, gifbase)

    @staticmethod
    def check_name(cell):
        """verifies that the data is string-able"""
        cell_value = cell.text()
        try:
            text = str(cell_value).strip()
        except UnicodeEncodeError:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

        if len(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    def check_path(self, cell):
        """verifies that the path exists"""
        text, passed = self.check_name(cell)
        if not passed:
            return None, False

        if os.path.exists(text):
            cell.setStyleSheet("QLineEdit{background: white;}")
            return text, True
        else:
            cell.setStyleSheet("QLineEdit{background: red;}")
            return None, False

    #def on_ok(self):
    #"""click the OK button"""
    #passed = self.on_apply()
    #if passed:
    #self.win_parent._animation_window_shown = False
    #self.close()
    ##self.destroy()

    def on_cancel(self):
        """click the Cancel button"""
        self.on_stop()
        self.out_data['close'] = True
        self.close()
Beispiel #20
0
class InterpolateDialog(QDialog):
    def __init__(self, spacing, *args, **kwargs):
        super().__init__(*args, **kwargs)
        min_val = min(spacing)
        start_value = [x / min_val for x in spacing]
        info_label = QLabel()
        info_label.setText(
            "This operation cannot be undone,\nit also update image spacing")
        self.start_value = start_value
        self.spacing = spacing
        self.x_spacing = QDoubleSpinBox()
        self.x_spacing.setRange(0, 100)
        self.x_spacing.setSingleStep(0.1)
        self.x_spacing.setDecimals(2)
        self.x_spacing.setValue(start_value[-1])
        self.y_spacing = QDoubleSpinBox()
        self.y_spacing.setRange(0, 100)
        self.y_spacing.setSingleStep(0.1)
        self.y_spacing.setDecimals(2)
        self.y_spacing.setValue(start_value[-2])
        self.z_spacing = QDoubleSpinBox()
        self.z_spacing.setRange(0, 100)
        self.z_spacing.setSingleStep(0.1)
        self.z_spacing.setDecimals(2)
        if len(start_value) == 3:
            self.z_spacing.setValue(start_value[0])
        else:
            self.z_spacing.setDisabled(True)

        self.accept_button = QPushButton("Interpolate")
        self.accept_button.clicked.connect(self.accept)
        self.cancel_button = QPushButton("Cancel")
        self.cancel_button.clicked.connect(self.reject)

        layout = QGridLayout()
        layout.addWidget(info_label, 0, 0, 1, 2)
        layout.addWidget(QLabel("x scale"), 1, 0)
        layout.addWidget(self.x_spacing, 1, 1)
        layout.addWidget(QLabel("y scale"), 2, 0)
        layout.addWidget(self.y_spacing, 2, 1)
        if len(start_value) == 3:
            layout.addWidget(QLabel("z scale"), 3, 0)
            layout.addWidget(self.z_spacing, 3, 1)
        layout.addWidget(self.accept_button, 4, 0)
        layout.addWidget(self.cancel_button, 4, 1)
        self.setLayout(layout)

    def get_zoom_factor(self):
        if len(self.start_value) == 3:
            return 1, self.z_spacing.value(), self.y_spacing.value(
            ), self.x_spacing.value()

        return 1, self.y_spacing.value(), self.x_spacing.value()

    def get_new_spacing(self):
        if len(self.start_value) == 3:
            return [
                self.spacing[0] / self.x_spacing.value(),
                self.spacing[1] / self.y_spacing.value(),
                self.spacing[2] / self.z_spacing.value(),
            ]

        return [
            self.spacing[0] / self.x_spacing.value(),
            self.spacing[1] / self.y_spacing.value(), 1
        ]
Beispiel #21
0
class EditNodeProperties(QDialog):
    def __init__(self, data, win_parent=None):
        """
        +-----------------+
        | Edit Node Props |
        +-----------------+------+
        |  LEwingTip             |
        |  Node2                 |
        |  Node3                 |
        |  Node4                 |
        |                        |
        |  All Nodes:            |
        |    Color     red       |
        |    PointSize 3         |
        |    Opacity   0.3       |
        |    Show/Hide           |
        |                        |
        |  Name        LEwingTip |
        |  Location    X Y Z     |
        |  Coord       0         |
        |  CoordType   R, C, S   |
        |                        |
        |   Previous     Next    |
        |                        |
        |          Close         |
        +------------------------+
        """
        QDialog.__init__(self, win_parent)
        self.setWindowTitle('Edit Node Properties')

        #default
        self.win_parent = win_parent
        self.out_data = data

        point_properties = data['point_properties']
        print(point_properties)
        #name = point_properties.name
        point_size = point_properties.point_size
        opacity = point_properties.opacity
        color = point_properties.color
        show = point_properties.is_visible

        self.points = data['points']

        self.keys = sorted(self.points.keys())
        keys = self.keys
        #nrows = len(keys)

        active_point = data['active_point']
        #self.active_key = keys[0]
        self.active_key = active_point
        name = self.active_key
        description = self.points[self.active_key][0]

        self._use_old_table = False
        items = ['Node %i' % val for val in keys]
        header_labels = ['Nodes']
        table_model = Model(items, header_labels, self)
        view = SingleChoiceQTableView(self)  #Call your custom QTableView here
        view.setModel(table_model)
        if qt_version == 4:
            view.horizontalHeader().setResizeMode(QHeaderView.Stretch)
        else:
            view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.table = view

        #self.representation = actor_obj.representation
        #print('rep =', self.representation)

        table = self.table
        #headers = [QtCore.QString('Groups')]

        header = table.horizontalHeader()
        header.setStretchLastSection(True)

        #----------------------------------------------
        #self._default_is_apply = False

        self.color = QLabel("Color:")
        self.color_edit = QPushButton()
        #self.color_edit.setFlat(True)

        color = self.out_data['point_properties'].color
        opacity = self.out_data['point_properties'].opacity
        show = self.out_data['point_properties'].is_visible
        #color = self.out_data[self.active_key].color
        qcolor = QColor()
        qcolor.setRgb(*color)
        #print('color =%s' % str(color))
        palette = QPalette(
            self.color_edit.palette())  # make a copy of the palette
        #palette.setColor(QPalette.Active, QPalette.Base, \
        #qcolor)
        palette.setColor(QPalette.Background, QColor('blue'))  # ButtonText
        self.color_edit.setPalette(palette)

        self.color_edit.setStyleSheet("QPushButton {"
                                      "background-color: rgb(%s, %s, %s);" %
                                      tuple(color) +
                                      #"border:1px solid rgb(255, 170, 255); "
                                      "}")

        self.all_nodes_header = QLabel("All Nodes:")
        self.point_size = QLabel("Point Size:")
        self.point_size_edit = QSpinBox(self)
        self.point_size_edit.setRange(1, 10)
        self.point_size_edit.setSingleStep(1)
        self.point_size_edit.setValue(point_size)

        self.opacity = QLabel("Opacity:")
        self.opacity_edit = QDoubleSpinBox(self)
        self.opacity_edit.setRange(0.1, 1.0)
        self.opacity_edit.setDecimals(1)
        self.opacity_edit.setSingleStep(0.1)
        self.opacity_edit.setValue(opacity)

        # show/hide
        self.checkbox_show = QCheckBox("Show")
        self.checkbox_hide = QCheckBox("Hide")
        self.checkbox_show.setChecked(show)
        self.checkbox_hide.setChecked(not show)

        #----------------------------------------------
        self.nodes_header = QLabel("Single Node:")
        self.name = QLabel("ID:")
        self.name_edit = QLineEdit('Node %i' % name)
        self.name_edit.setDisabled(True)

        self.description = QLabel("Description:")
        self.description_edit = QLineEdit(str(description))
        #self.description_edit.setDisabled(True)

        location_x = 0.1
        location_y = 0.1
        location_z = 0.1
        self.location = QLabel("Location:")
        self.location_x_edit = QDoubleSpinBox(self)
        self.location_y_edit = QDoubleSpinBox(self)
        self.location_z_edit = QDoubleSpinBox(self)
        #self.location_x_edit.setDecimals(1)
        delta_x = abs(location_x) / 100. if location_x != 0.0 else 0.1
        delta_y = abs(location_y) / 100. if location_y != 0.0 else 0.1
        delta_z = abs(location_z) / 100. if location_z != 0.0 else 0.1
        self.location_x_edit.setSingleStep(delta_x)
        self.location_y_edit.setSingleStep(delta_y)
        self.location_z_edit.setSingleStep(delta_z)
        self.location_x_edit.setValue(location_x)
        self.location_y_edit.setValue(location_y)
        self.location_z_edit.setValue(location_z)

        self.coord = QLabel("Coord:")
        self.coord_edit = QSpinBox(self)
        self.coord_edit.setRange(0, 99999999)
        #self.coord_edit.setSingleStep(1)
        self.coord_edit.setValue(0)

        self.coord_type = QLabel("Coord Type:")
        #----------------------------------------------

        # closing
        #if self._default_is_apply:
        #self.apply_button.setDisabled(True)

        self.close_button = QPushButton("Close")

        self.create_layout()
        self.set_connections()

    def update_active_key(self, index):
        name = self.active_key
        old_obj = self.out_data['points'][name]
        #self.active_key
        #self.points[self.active_key]
        old_obj[0] = str(self.description_edit.text())
        #old_obj.coord = self.description_edit.value()
        #old_obj.description = self.description_edit.value()
        #old_obj.description = self.description_edit.value()

        str_name = str(index.data().toString())
        name = int(str_name[5:])
        #i = self.keys.index(self.active_key)

        self.active_key = name
        point = self.points[self.active_key]

        #1  : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        self.name_edit.setText(str(self.active_key))
        self.description_edit.setText(point[0])

        self.coord_edit.setValue(point[1])
        if point[2] == 'R':
            self.radio_rectangular.setChecked(True)
        elif point[2] == 'C':
            self.radio_cylindrical.setChecked(True)
        elif point[2] == 'S':
            self.radio_spherical.setChecked(True)

        self.location_x_edit.setValue(point[3])
        self.location_y_edit.setValue(point[4])
        self.location_z_edit.setValue(point[5])
        #obj = self.out_data[name]
        #point_size = obj.point_size
        #opacity = obj.opacity
        #representation = obj.representation
        #is_visible = obj.is_visible

        #self.opacity_edit.setValue(opacity)
        #self.checkbox_show.setChecked(is_visible)
        #self.checkbox_hide.setChecked(not is_visible)

    #def on_name_select(self):
    #print('on_name_select')
    #return

    def create_layout(self):
        cancel_box = QHBoxLayout()
        cancel_box.addWidget(self.close_button)

        grid1 = QGridLayout()
        grid2 = QGridLayout()

        #-----------------------------------------
        # setup
        self.radio_rectangular = QRadioButton('Rectangular')
        self.radio_cylindrical = QRadioButton('Cylindrical')
        self.radio_spherical = QRadioButton('Spherical')

        coord_type_layout = QHBoxLayout()
        coord_type_layout.addWidget(self.radio_rectangular)
        coord_type_layout.addWidget(self.radio_cylindrical)
        coord_type_layout.addWidget(self.radio_spherical)

        location_layout = QHBoxLayout()
        location_layout.addWidget(self.location_x_edit)
        location_layout.addWidget(self.location_y_edit)
        location_layout.addWidget(self.location_z_edit)

        checkboxs = QButtonGroup(self)
        checkboxs.addButton(self.checkbox_show)
        checkboxs.addButton(self.checkbox_hide)

        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.checkbox_show)
        vbox1.addWidget(self.checkbox_hide)
        #vbox1.addLayout(checkboxs)

        #-----------------------------------------
        irow = 0
        grid1.addWidget(self.all_nodes_header, irow, 0)
        irow += 1

        grid1.addWidget(self.color, irow, 0)
        grid1.addWidget(self.color_edit, irow, 1)
        irow += 1

        grid1.addWidget(self.opacity, irow, 0)
        grid1.addWidget(self.opacity_edit, irow, 1)
        irow += 1

        grid1.addWidget(self.point_size, irow, 0)
        grid1.addWidget(self.point_size_edit, irow, 1)
        irow += 1

        #-----------------------------------------
        irow = 0
        grid2.addWidget(self.nodes_header, irow, 0)
        irow += 1

        grid2.addWidget(self.name, irow, 0)
        grid2.addWidget(self.name_edit, irow, 1)
        irow += 1

        grid2.addWidget(self.description, irow, 0)
        grid2.addWidget(self.description_edit, irow, 1)
        irow += 1

        #|  All Nodes:            |
        #|    Color     red       |
        #|    PointSize 3         |
        #|    Opacity   0.3       |
        #|    Show/Hide           |
        #|                        |
        #|  Name        LEwingTip |
        #|  Location    X Y Z     |
        #|  Coord       0         |
        #|  CoordType   R, C, S   |
        #|                        |
        #|   Previous     Next    |
        grid2.addWidget(self.coord, irow, 0)
        grid2.addWidget(self.coord_edit, irow, 1)
        irow += 1

        grid2.addWidget(self.coord_type, irow, 0)
        grid2.addLayout(coord_type_layout, irow, 1)
        irow += 1

        grid2.addWidget(self.location, irow, 0)
        grid2.addLayout(location_layout, irow, 1)
        irow += 1

        #------------------------------------

        vbox = QVBoxLayout()
        vbox.addLayout(grid1)
        vbox.addLayout(vbox1)
        vbox.addStretch()
        vbox.addWidget(self.table)

        vbox.addLayout(grid2)
        vbox.addStretch()
        #vbox.addWidget(self.check_apply)
        vbox.addLayout(cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        if qt_version == 4:
            self.connect(self.opacity_edit, QtCore.SIGNAL('clicked()'),
                         self.on_opacity)
            self.connect(self.point_size, QtCore.SIGNAL('clicked()'),
                         self.on_point_size)
            self.connect(self.color_edit, QtCore.SIGNAL('clicked()'),
                         self.on_color)
            self.connect(self.checkbox_show, QtCore.SIGNAL('clicked()'),
                         self.on_show)
            self.connect(self.checkbox_hide, QtCore.SIGNAL('clicked()'),
                         self.on_hide)

            self.connect(self.description_edit,
                         QtCore.SIGNAL("valueChanged(int)"),
                         self.on_description)
            self.connect(self.coord_edit, QtCore.SIGNAL("valueChanged(int)"),
                         self.on_coord)
            self.connect(self.radio_rectangular, QtCore.SIGNAL('clicked()'),
                         self.on_coord_type)
            self.connect(self.radio_cylindrical, QtCore.SIGNAL('clicked()'),
                         self.on_coord_type)
            self.connect(self.radio_spherical, QtCore.SIGNAL('clicked()'),
                         self.on_coord_type)

            self.connect(self.location_x_edit, QtCore.SIGNAL('clicked()'),
                         self.on_location_x)
            self.connect(self.location_y_edit, QtCore.SIGNAL('clicked()'),
                         self.on_location_y)
            self.connect(self.location_z_edit, QtCore.SIGNAL('clicked()'),
                         self.on_location_z)

            self.connect(self.close_button, QtCore.SIGNAL('clicked()'),
                         self.on_close)

            #self.connect(self.check_apply, QtCore.SIGNAL('clicked()'), self.on_check_apply)

            #self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
            #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
            #self.connect(self.close_button, QtCore.SIGNAL('clicked()'), self.on_close)
        else:
            #self.opacity_edit.clicked.connect(self.on_opacity)
            #self.point_size.clicked.connect(self.on_point_size)
            #self.color_edit.clicked.connect(self.on_color)
            #self.checkbox_show.clicked.connect(self.on_show)
            #self.checkbox_hide.clicked.connect(self.on_hide)

            #self.description_edit.valueChanged.connect(self.on_description)
            #self.coord_edit.valueChanged.connect(self.on_coord)
            #self.radio_rectangular.clicked.connect(self.on_coord_type)
            #self.radio_cylindrical.clicked.connect(self.on_coord_type)
            #self.radio_spherical.clicked.connect(self.on_coord_type)

            #self.location_x_edit.clicked.connect(self.on_location_x)
            #self.location_y_edit.clicked.connect(self.on_location_y)
            #self.location_z_edit.clicked.connect(self.on_location_z)
            self.close_button.clicked.connect(self.on_close)

    def on_color(self):
        obj = self.out_data['point_properties']
        rgb_color_ints = obj.color

        msg = 'Points'
        col = QColorDialog.getColor(QColor(*rgb_color_ints), self,
                                    "Choose a %s color" % msg)
        if col.isValid():
            color = col.getRgbF()[:3]
            obj.color = color
            #print('new_color =', color)
            self.color_edit.setStyleSheet(
                "QPushButton {"
                "background-color: rgb(%s, %s, %s);" % tuple(obj.color) +
                #"border:1px solid rgb(255, 170, 255); "
                "}")

    def on_show(self):
        is_checked = self.checkbox_show.isChecked()
        self.out_data['point_properties'].is_visible = is_checked

    def on_hide(self):
        is_checked = self.checkbox_hide.isChecked()
        self.out_data['point_properties'].is_visible = not is_checked

    def on_point_size(self):
        point_size = self.point_size_edit.value()
        self.out_data['point_properties'].point_size = point_size

    def on_opacity(self):
        opacity = self.opacity_edit.value()
        self.out_data['point_properties'].opacity = opacity

    def on_description(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        description = self.description_edit.value()
        self.out_data['points'][name][0] = description

    def on_coord(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        coord_id = self.coord_edit.value()
        self.out_data['points'][name][1] = coord_id

    def on_coord_type(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        if self.radio_rectangular.isChecked():
            coord_type = 'R'
        elif self.radio_cylindrical.isChecked():
            coord_type = 'C'
        elif self.radio_spherical.isChecked():
            coord_type = 'S'
        else:
            raise NotImplementedError()
        self.out_data['points'][name][2] = coord_type

    def on_location_x(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][3] = value

    def on_location_y(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][4] = value

    def on_location_z(self):
        #1 : ['LERoot', 0, 'R', 1.0, 2.0, 3.0],
        name = self.active_key
        value = self.coord_edit.value()
        self.out_data['points'][name][5] = value

    def closeEvent(self, event):
        event.accept()

    #def on_default_name(self):
    #self.name_edit.setText(str(self._default_name))
    #self.name_edit.setStyleSheet("QLineEdit{background: white;}")

    #def check_name(self, cell):
    #text = str(cell.text()).strip()
    #if len(text):
    #cell.setStyleSheet("QLineEdit{background: white;}")
    #return text, True
    #else:
    #cell.setStyleSheet("QLineEdit{background: red;}")
    #return None, False

    def on_validate(self):
        self.out_data['clicked_ok'] = True
        self.out_data['clicked_cancel'] = False

        old_obj = self.out_data[self.active_key]
        old_obj.point_size = self.point_size_edit.value()
        old_obj.opacity = self.opacity_edit.value()
        old_obj.is_visible = self.checkbox_show.isChecked()
        return True
        #name_value, flag0 = self.check_name(self.name_edit)
        #ox_value, flag1 = check_float(self.transparency_edit)
        #if flag0 and flag1:
        #self.out_data['clicked_ok'] = True
        #return True
        #return False

    def on_apply(self):
        passed = self.on_validate()
        if passed:
            self.win_parent.on_update_gui_nodes(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_close(self):
        self.out_data['clicked_close'] = True
        self.close()
Beispiel #22
0
class HighlightWindow(PyDialog):
    """
    +-----------+
    | Highlight |
    +--------------------------+
    | Nodes     ______         |
    | Elements  ______         |
    |                          |
    |     Highlight Close      |
    +--------------------------+
    """
    def __init__(self, data, menu_type, win_parent=None):
        """
        Saves the data members from data and
        performs type checks

        Parameters
        ----------
        menu_type : str
            'highlight'
            'mark'

        """
        PyDialog.__init__(self, data, win_parent)
        gui = win_parent
        self.menu_type = menu_type

        self._default_annotation_size = ANNOTATION_SIZE
        if gui is None:  # pragma: no cover
            self.highlight_color_float = [0., 0., 0.]
            self.highlight_color_int = [0, 0, 0]
            self._highlight_opacity = 0.9
            self._point_size = 10
            self._label_size = 10.0
        else:
            settings = gui.settings  # type: Settings
            self.highlight_color_float, self.highlight_color_int = check_color(
                settings.highlight_color)

            self._highlight_opacity = settings.highlight_opacity

            self._point_size = settings.highlight_point_size
            self._line_thickness = settings.highlight_line_thickness

            self._point_size = 10
            self._annotation_size = settings.annotation_size
        self._updated_window = False

        self.actors = []
        self._default_font_size = data['font_size']
        self.model_name = data['model_name']
        assert len(self.model_name) > 0, self.model_name

        #self._default_annotation_size = data['annotation_size'] # int
        #self.default_magnify = data['magnify']

        if 'nodes_pound' in data:  # testing
            nodes_pound = data['nodes_pound']
            elements_pound = data['elements_pound']
            nodes = np.arange(1, nodes_pound + 1)
            elements = np.arange(1, elements_pound + 1)
        else:
            # gui
            nodes = gui.get_node_ids(model_name=self.model_name)
            elements = gui.get_element_ids(model_name=self.model_name)
            nodes_pound = nodes.max()
            elements_pound = elements.max()

        self.nodes = nodes
        self.elements = elements
        self._nodes_pound = nodes_pound
        self._elements_pound = elements_pound

        if self.menu_type == 'highlight':
            self.setWindowTitle('Highlight')
        elif self.menu_type == 'mark':
            self.setWindowTitle('Mark')
        else:
            raise NotImplementedError(self.menu_type)

        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        #self.show()

    def create_widgets(self):
        """creates the display window"""
        # Text Size

        model_name = self.model_name
        self.nodes_label = QLabel('Nodes:')
        self.nodes_edit = QNodeEdit(self,
                                    model_name,
                                    pick_style='area',
                                    cleanup=True,
                                    tab_to_next=False)

        self.elements_label = QLabel('Elements:')
        self.elements_edit = QElementEdit(self,
                                          model_name,
                                          pick_style='area',
                                          cleanup=True,
                                          tab_to_next=False)

        #-----------------------------------------------------------------------
        # Highlight Color
        if self.menu_type == 'highlight':
            self.highlight_opacity_label = QLabel('Highlight Opacity:')
            self.highlight_opacity_edit = QDoubleSpinBox(self)
            self.highlight_opacity_edit.setValue(self._highlight_opacity)
            self.highlight_opacity_edit.setRange(0.1, 1.0)
            self.highlight_opacity_edit.setDecimals(1)
            self.highlight_opacity_edit.setSingleStep(0.1)
            self.highlight_opacity_button = QPushButton('Default')

            # Text Color
            self.highlight_color_label = QLabel('Highlight Color:')
            self.highlight_color_edit = QPushButtonColor(
                self.highlight_color_int)

            self.point_size_label = QLabel('Point Size:')
            self.point_size_edit = QSpinBox(self)
            self.point_size_edit.setValue(self._point_size)
            self.point_size_edit.setRange(7, 30)
            #self.point_size_button = QPushButton("Default")
        elif self.menu_type == 'mark':
            self.label_size_label = QLabel('Label Size:')
            self.label_size_edit = QSpinBox(self)
            self.label_size_edit.setValue(self._default_annotation_size)
            self.label_size_edit.setRange(7, 30)
            #self.label_size_button = QPushButton("Default")
        else:
            raise NotImplementedError(self.menu_type)
        #-----------------------------------------------------------------------
        # closing
        #if self.menu_type == 'highlight':
        self.show_button = QPushButton('Show')
        #elif self.menu_type == 'mark':
        #self.mark_button = QCheckBox('Mark')
        #else:
        #raise NotImplementedError(self.menu_type)
        self.clear_button = QPushButton('Clear')
        self.close_button = QPushButton('Close')

    def create_layout(self):
        """displays the menu objects"""
        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.nodes_label, irow, 0)
        grid.addWidget(self.nodes_edit, irow, 1)
        irow += 1

        grid.addWidget(self.elements_label, irow, 0)
        grid.addWidget(self.elements_edit, irow, 1)
        irow += 1

        if self.menu_type == 'highlight':
            # TODO: enable me
            grid.addWidget(self.highlight_color_label, irow, 0)
            grid.addWidget(self.highlight_color_edit, irow, 1)
            self.highlight_color_label.setEnabled(False)
            self.highlight_color_edit.setEnabled(False)
            irow += 1

            # TODO: enable me
            grid.addWidget(self.highlight_opacity_label, irow, 0)
            grid.addWidget(self.highlight_opacity_edit, irow, 1)
            self.highlight_opacity_label.setEnabled(False)
            self.highlight_opacity_edit.setEnabled(False)
            irow += 1

            # TODO: enable me
            grid.addWidget(self.point_size_label, irow, 0)
            grid.addWidget(self.point_size_edit, irow, 1)
            self.point_size_label.setEnabled(False)
            self.point_size_edit.setEnabled(False)
            irow += 1
        elif self.menu_type == 'mark':
            # TODO: enable me
            grid.addWidget(self.label_size_label, irow, 0)
            grid.addWidget(self.label_size_edit, irow, 1)
            #self.label_size_label.setEnabled(False)
            #self.label_size_edit.setEnabled(False)
            irow += 1
            #self.mark_button.setEnabled(False)
        else:
            raise NotImplementedError(self.menu_type)

        #self.create_legend_widgets()
        #grid2 = self.create_legend_layout()
        ok_cancel_box = QHBoxLayout()
        #if self.menu_type == 'highlight':
        ok_cancel_box.addWidget(self.show_button)
        #elif self.menu_type == 'mark':
        #ok_cancel_box.addWidget(self.mark_button)
        #else:
        #raise NotImplementedError(self.menu_type)
        ok_cancel_box.addWidget(self.clear_button)
        ok_cancel_box.addWidget(self.close_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        #vbox.addStretch()
        #vbox.addLayout(grid2)
        vbox.addStretch()

        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        if self.menu_type == 'highlight':
            self._set_connections_highlight()
        elif self.menu_type == 'mark':
            self._set_connections_mark()
        else:
            raise NotImplementedError(self.menu_type)
        self._set_connections_end()

    def _set_connections_highlight(self):
        """creates the actions for the menu"""
        self.highlight_color_edit.clicked.connect(self.on_highlight_color)
        self.highlight_opacity_edit.valueChanged.connect(
            self.on_highlight_opacity)
        self.show_button.clicked.connect(self.on_show)

    def _set_connections_mark(self):
        """creates the actions for the menu"""
        self.show_button.clicked.connect(self.on_show)

    def _set_connections_end(self):
        """creates the actions for the menu"""
        self.nodes_edit.textChanged.connect(self.on_validate)
        self.elements_edit.textChanged.connect(self.on_validate)
        self.clear_button.clicked.connect(self.on_remove_actors)
        self.close_button.clicked.connect(self.on_close)

    def on_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)

    def on_highlight_color(self):
        """
        Choose a highlight color

        TODO: not implemented
        """
        title = "Choose a highlight color"
        rgb_color_ints = self.highlight_color_int
        color_edit = self.highlight_color_edit
        func_name = 'set_highlight_color'
        passed, rgb_color_ints, rgb_color_floats = create_color_menu(
            self, self.win_parent, title, color_edit, rgb_color_ints,
            func_name)
        if passed:
            self.highlight_color_int = rgb_color_ints
            self.highlight_color_float = rgb_color_floats

    def on_highlight_opacity(self, value=None):
        """
        update the highlight opacity

        TODO: not implemented
        """
        if value is None:
            value = self.highlight_opacity_edit.value()
        self._highlight_opacity = value
        if self.win_parent is not None:
            self.win_parent.settings.set_highlight_opacity(value)

    #---------------------------------------------------------------------------

    def on_validate(self):
        """makes sure that all attributes are valid before doing any actions"""
        unused_nodes, flag1 = check_patran_syntax(self.nodes_edit,
                                                  pound=self._nodes_pound)
        unused_elements, flag2 = check_patran_syntax(
            self.elements_edit, pound=self._elements_pound)
        if all([flag1, flag2]):
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_show(self):
        """show the highlight"""
        passed = self.on_validate()
        if not passed or self.win_parent is None:
            return passed
        self.parent().mouse_actions.get_grid_selected(self.model_name)

        nodes, unused_flag1 = check_patran_syntax(self.nodes_edit,
                                                  pound=self._nodes_pound)
        elements, unused_flag2 = check_patran_syntax(
            self.elements_edit, pound=self._elements_pound)
        if len(nodes) == 0 and len(elements) == 0:
            return False
        nodes_filtered = np.intersect1d(self.nodes, nodes)
        elements_filtered = np.intersect1d(self.elements, elements)
        nnodes = len(nodes_filtered)
        nelements = len(elements_filtered)
        if nnodes == 0 and nelements == 0:
            return False
        self.on_remove_actors()

        gui = self.parent()
        mouse_actions = gui.mouse_actions
        grid = mouse_actions.get_grid_selected(self.model_name)

        actors = create_highlighted_actors(gui,
                                           grid,
                                           all_nodes=self.nodes,
                                           nodes=nodes_filtered,
                                           set_node_scalars=True,
                                           all_elements=self.elements,
                                           elements=elements_filtered,
                                           set_element_scalars=True,
                                           add_actors=False)

        #make_highlight = self.menu_type == 'highlight'
        make_labels = self.menu_type == 'mark'
        make_element_labels = True
        make_node_labels = True

        if make_labels:
            actors = self._save_mark_actors(gui, make_node_labels,
                                            make_element_labels, nnodes,
                                            nelements, actors)

        if actors:
            add_actors_to_gui(gui, actors, render=True)
            self.actors = actors
        gui.Render()
        return passed

    def _save_mark_actors(self, gui, make_node_labels, make_element_labels,
                          nnodes, nelements, actors):
        """replace the actors with labels"""
        iactor = 0
        actors2 = []
        if make_node_labels and nnodes:
            mapper = actors[iactor].GetMapper()
            mygrid = mapper.GetInput()

            point_id_filter = get_ids_filter(mygrid,
                                             idsname='Ids_points',
                                             is_nids=True,
                                             is_eids=False)
            point_id_filter.SetFieldData(1)
            point_id_filter.SetPointIds(0)
            point_id_filter.FieldDataOn()

            label_actor = create_node_labels(point_id_filter,
                                             mygrid,
                                             gui.rend,
                                             label_size=self._annotation_size)
            #actors.append(label_actor)
            actors2.append(label_actor)
            iactor += 1

        if make_element_labels and nelements:
            mapper = actors[iactor].GetMapper()
            mygrid = mapper.GetInput()

            element_id_filter = get_ids_filter(mygrid,
                                               idsname='Ids_cells',
                                               is_nids=False,
                                               is_eids=True)
            element_id_filter.SetFieldData(1)
            element_id_filter.SetCellIds(0)
            element_id_filter.FieldDataOn()

            # Create labels for cells
            cell_centers = vtk.vtkCellCenters()
            cell_centers.SetInputConnection(element_id_filter.GetOutputPort())

            cell_mapper = vtk.vtkLabeledDataMapper()
            cell_mapper.SetInputConnection(cell_centers.GetOutputPort())
            cell_mapper.SetLabelModeToLabelScalars()

            label_actor = vtk.vtkActor2D()
            label_actor.SetMapper(cell_mapper)

            #actors.append(label_actor)
            actors2.append(label_actor)
            iactor += 1
        return actors2

    def on_remove_actors(self):
        """removes multiple vtk actors"""
        gui = self.parent()
        if gui is not None:
            if self.nodes_edit.style is not None:
                self.nodes_edit.style.remove_actors()
            if self.elements_edit.style is not None:
                self.elements_edit.style.remove_actors()
            remove_actors_from_gui(gui,
                                   self.actors,
                                   render=True,
                                   force_render=True)
            gui.Render()
        self.actors = []

    def closeEvent(self, unused_event):
        """close the window"""
        self.on_close()

    def on_close(self):
        """close the window"""
        self.on_remove_actors()
        self.out_data['close'] = True
        self.close()
Beispiel #23
0
class QtVectorsControls(QtLayerControls):
    """Qt view and controls for the napari Vectors layer.

    Parameters
    ----------
    layer : napari.layers.Vectors
        An instance of a napari Vectors layer.

    Attributes
    ----------
    edge_color_label : qtpy.QtWidgets.QLabel
        Label for edgeColorSwatch
    edgeColorSwatch : qtpy.QtWidgets.QFrame
        Color swatch showing display color of vectors.
    edgeComboBox : qtpy.QtWidgets.QComboBox
        Dropdown widget to select display color for vectors.
    color_mode_comboBox : qtpy.QtWidgets.QComboBox
        Dropdown widget to select edge_color_mode for the vectors.
    color_prop_box : qtpy.QtWidgets.QComboBox
        Dropdown widget to select _edge_color_property for the vectors.
    edge_prop_label : qtpy.QtWidgets.QLabel
        Label for color_prop_box
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : napari.layers.Vectors
        An instance of a napari Vectors layer.
    lengthSpinBox : qtpy.QtWidgets.QDoubleSpinBox
        Spin box widget controlling line length of vectors.
        Multiplicative factor on projections for length of all vectors.
    widthSpinBox : qtpy.QtWidgets.QDoubleSpinBox
        Spin box widget controlling edge line width of vectors.
    """
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.length.connect(self._on_length_change)
        self.layer.events.edge_color_mode.connect(
            self._on_edge_color_mode_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)

        # dropdown to select the property for mapping edge_color
        color_properties = self._get_property_values()
        color_prop_box = QComboBox(self)
        color_prop_box.activated[str].connect(self.change_edge_color_property)
        color_prop_box.addItems(color_properties)
        self.color_prop_box = color_prop_box
        self.edge_prop_label = QLabel(trans._('edge property:'))

        # vector direct color mode adjustment and widget
        self.edgeColorEdit = QColorSwatchEdit(
            initial_color=self.layer.edge_color,
            tooltip=trans._('click to set current edge color', ),
        )
        self.edgeColorEdit.color_changed.connect(self.change_edge_color_direct)
        self.edge_color_label = QLabel(trans._('edge color:'))
        self._on_edge_color_change()

        # dropdown to select the edge color mode
        colorModeComboBox = QComboBox(self)
        colorModeComboBox.addItems(ColorMode.keys())
        colorModeComboBox.activated[str].connect(self.change_edge_color_mode)
        self.color_mode_comboBox = colorModeComboBox
        self._on_edge_color_mode_change()

        # line width in pixels
        self.widthSpinBox = QDoubleSpinBox()
        self.widthSpinBox.setKeyboardTracking(False)
        self.widthSpinBox.setSingleStep(0.1)
        self.widthSpinBox.setMinimum(0.1)
        self.widthSpinBox.setValue(self.layer.edge_width)
        self.widthSpinBox.valueChanged.connect(self.change_width)

        # line length
        self.lengthSpinBox = QDoubleSpinBox()
        self.lengthSpinBox.setKeyboardTracking(False)
        self.lengthSpinBox.setSingleStep(0.1)
        self.lengthSpinBox.setValue(self.layer.length)
        self.lengthSpinBox.setMinimum(0.1)
        self.lengthSpinBox.valueChanged.connect(self.change_length)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 0, 0)
        self.grid_layout.addWidget(self.opacitySlider, 0, 1, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('width:')), 1, 0)
        self.grid_layout.addWidget(self.widthSpinBox, 1, 1, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('length:')), 2, 0)
        self.grid_layout.addWidget(self.lengthSpinBox, 2, 1, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 3, 0)
        self.grid_layout.addWidget(self.blendComboBox, 3, 1, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('edge color mode:')), 4, 0)
        self.grid_layout.addWidget(self.color_mode_comboBox, 4, 1, 1, 2)
        self.grid_layout.addWidget(self.edge_color_label, 5, 0)
        self.grid_layout.addWidget(self.edgeColorEdit, 5, 1, 1, 2)
        self.grid_layout.addWidget(self.edge_prop_label, 6, 0)
        self.grid_layout.addWidget(self.color_prop_box, 6, 1, 1, 2)
        self.grid_layout.setRowStretch(7, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def change_edge_color_property(self, property: str):
        """Change edge_color_property of vectors on the layer model.
        This property is the property the edge color is mapped to.

        Parameters
        ----------
        property : str
            property to map the edge color to
        """
        mode = self.layer.edge_color_mode
        try:
            self.layer.edge_color = property
            self.layer.edge_color_mode = mode
        except TypeError:
            # if the selected property is the wrong type for the current color mode
            # the color mode will be changed to the appropriate type, so we must update
            self._on_edge_color_mode_change()
            raise

    def change_edge_color_mode(self, mode: str):
        """Change edge color mode of vectors on the layer model.

        Parameters
        ----------
        mode : str
            Edge color for vectors. Must be: 'direct', 'cycle', or 'colormap'
        """
        old_mode = self.layer.edge_color_mode
        with self.layer.events.edge_color_mode.blocker():
            try:
                self.layer.edge_color_mode = mode
                self._update_edge_color_gui(mode)

            except ValueError:
                # if the color mode was invalid, revert to the old mode
                self.layer.edge_color_mode = old_mode
                raise

    def change_edge_color_direct(self, color: np.ndarray):
        """Change edge color of vectors on the layer model.

        Parameters
        ----------
        color : np.ndarray
            Edge color for vectors, in an RGBA array
        """
        self.layer.edge_color = color

    def change_width(self, value):
        """Change edge line width of vectors on the layer model.

        Parameters
        ----------
        value : float
            Line width of vectors.
        """
        self.layer.edge_width = value
        self.widthSpinBox.clearFocus()
        self.setFocus()

    def change_length(self, value):
        """Change length of vectors on the layer model.

        Multiplicative factor on projections for length of all vectors.

        Parameters
        ----------
        value : float
            Length of vectors.
        """
        self.layer.length = value
        self.lengthSpinBox.clearFocus()
        self.setFocus()

    def _update_edge_color_gui(self, mode: str):
        """Update the GUI element associated with edge_color.
        This is typically used when edge_color_mode changes

        Parameters
        ----------
        mode : str
            The new edge_color mode the GUI needs to be updated for.
            Should be: 'direct', 'cycle', 'colormap'
        """
        if mode in ('cycle', 'colormap'):
            self.edgeColorEdit.setHidden(True)
            self.edge_color_label.setHidden(True)
            self.color_prop_box.setHidden(False)
            self.edge_prop_label.setHidden(False)

        elif mode == 'direct':
            self.edgeColorEdit.setHidden(False)
            self.edge_color_label.setHidden(False)
            self.color_prop_box.setHidden(True)
            self.edge_prop_label.setHidden(True)

    def _get_property_values(self):
        """Get the current property values from the Vectors layer

        Returns
        -------
        property_values : np.ndarray
            array of all of the union of the property names (keys)
            in Vectors.properties and Vectors._property_choices

        """
        property_choices = [*self.layer._property_choices]
        properties = [*self.layer.properties]
        property_values = np.union1d(property_choices, properties)

        return property_values

    def _on_length_change(self, event=None):
        """Change length of vectors.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method, by default None.
        """
        with self.layer.events.length.blocker():
            self.lengthSpinBox.setValue(self.layer.length)

    def _on_edge_width_change(self, event=None):
        """Receive layer model width change event and update width spinbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method, by default None.
        """
        with self.layer.events.edge_width.blocker():
            self.widthSpinBox.setValue(self.layer.edge_width)

    def _on_edge_color_mode_change(self, event=None):
        """Receive layer model edge color mode change event & update dropdown.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method, by default None.
        """
        with qt_signals_blocked(self.color_mode_comboBox):
            mode = self.layer.edge_color_mode
            index = self.color_mode_comboBox.findText(mode,
                                                      Qt.MatchFixedString)
            self.color_mode_comboBox.setCurrentIndex(index)

            self._update_edge_color_gui(mode)

    def _on_edge_color_change(self, event=None):
        """Receive layer model edge color  change event & update dropdown.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method, by default None.
        """
        if self.layer._edge_color_mode == ColorMode.DIRECT:
            with qt_signals_blocked(self.edgeColorEdit):
                self.edgeColorEdit.setColor(self.layer.edge_color[0])
        elif self.layer._edge_color_mode in (
                ColorMode.CYCLE,
                ColorMode.COLORMAP,
        ):
            with qt_signals_blocked(self.color_prop_box):
                prop = self.layer._edge_color_property
                index = self.color_prop_box.findText(prop, Qt.MatchFixedString)
                self.color_prop_box.setCurrentIndex(index)
Beispiel #24
0
class ChannelProperty(QWidget):
    """
    For manipulate chanel properties.
        1. Apply gaussian blur to channel
        2. Fixed range for coloring

    In future should be extended

    :param settings: for storing internal state. allow keep state between sessions
    :param start_name: name used to select proper information from settings object.
        Introduced for case with multiple image view.
    """
    def __init__(self, settings: ViewSettings, start_name: str):
        super().__init__()
        if start_name == "":
            raise ValueError(
                "ChannelProperty should have non empty start_name")
        self.current_name = start_name
        self.current_channel = 0
        self._settings = settings
        self.widget_dict: typing.Dict[str, ColorComboBoxGroup] = {}

        self.minimum_value = CustomSpinBox(self)
        self.minimum_value.setRange(-(10**6), 10**6)
        self.minimum_value.valueChanged.connect(self.range_changed)
        self.maximum_value = CustomSpinBox(self)
        self.maximum_value.setRange(-(10**6), 10**6)
        self.maximum_value.valueChanged.connect(self.range_changed)
        self.fixed = QCheckBox("Fix range")
        self.fixed.stateChanged.connect(self.lock_channel)
        self.use_filter = EnumComboBox(NoiseFilterType)
        self.use_filter.setToolTip("Only current channel")
        self.filter_radius = QDoubleSpinBox()
        self.filter_radius.setSingleStep(0.1)
        self.filter_radius.valueChanged.connect(self.gauss_radius_changed)
        self.use_filter.currentIndexChanged.connect(self.gauss_use_changed)
        self.gamma_value = QDoubleSpinBox()
        self.gamma_value.setRange(0.01, 100)
        self.gamma_value.setSingleStep(0.1)
        self.gamma_value.valueChanged.connect(self.gamma_value_changed)

        self.collapse_widget = CollapseCheckbox("Channel property")
        self.collapse_widget.add_hide_element(self.minimum_value)
        self.collapse_widget.add_hide_element(self.maximum_value)
        self.collapse_widget.add_hide_element(self.fixed)
        self.collapse_widget.add_hide_element(self.use_filter)
        self.collapse_widget.add_hide_element(self.filter_radius)
        self.collapse_widget.add_hide_element(self.gamma_value)

        layout = QGridLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.collapse_widget, 0, 0, 1, 4)
        label1 = QLabel("Min bright:")
        layout.addWidget(label1, 1, 0)
        layout.addWidget(self.minimum_value, 1, 1)
        label2 = QLabel("Max bright:")
        layout.addWidget(label2, 2, 0)
        layout.addWidget(self.maximum_value, 2, 1)
        layout.addWidget(self.fixed, 1, 2, 1, 2)
        label3 = QLabel("Filter:")
        layout.addWidget(label3, 3, 0, 1, 1)
        layout.addWidget(self.use_filter, 3, 1, 1, 1)
        layout.addWidget(self.filter_radius, 3, 2, 1, 1)
        label4 = QLabel("Gamma:")
        layout.addWidget(label4, 4, 0, 1, 1)
        layout.addWidget(self.gamma_value, 4, 1, 1, 1)
        self.setLayout(layout)

        self.collapse_widget.add_hide_element(label1)
        self.collapse_widget.add_hide_element(label2)
        self.collapse_widget.add_hide_element(label3)
        self.collapse_widget.add_hide_element(label4)

    def send_info(self):
        """send info to """
        widget = self.widget_dict[self.current_name]
        widget.parameters_changed(self.current_channel)

    def register_widget(self, widget: "ColorComboBoxGroup"):
        if widget.name in self.widget_dict:
            raise ValueError(f"name {widget.name} already register")
        self.widget_dict[widget.name] = widget
        self.change_current(widget.name, 0)

    def change_current(self, name, channel):
        if name not in self.widget_dict:
            raise ValueError(f"name {name} not in register")
        self.current_name = name
        self.current_channel = channel
        block = self.blockSignals(True)
        self.minimum_value.blockSignals(True)
        self.minimum_value.setValue(
            self._settings.get_from_profile(
                f"{self.current_name}.range_{self.current_channel}",
                (0, 65000))[0])
        self.minimum_value.blockSignals(False)
        self.maximum_value.setValue(
            self._settings.get_from_profile(
                f"{self.current_name}.range_{self.current_channel}",
                (0, 65000))[1])
        self.use_filter.set_value(
            self._settings.get_from_profile(
                f"{self.current_name}.use_filter_{self.current_channel}",
                NoiseFilterType.No))
        self.filter_radius.setValue(
            self._settings.get_from_profile(
                f"{self.current_name}.filter_radius_{self.current_channel}",
                1))
        self.fixed.setChecked(
            self._settings.get_from_profile(
                f"{self.current_name}.lock_{self.current_channel}", False))
        self.gamma_value.setValue(
            self._settings.get_from_profile(
                f"{self.current_name}.gamma_value_{self.current_channel}", 1))
        self.blockSignals(block)

    def gamma_value_changed(self):
        self._settings.set_in_profile(
            f"{self.current_name}.gamma_value_{self.current_channel}",
            self.gamma_value.value())
        self.send_info()

    def gauss_radius_changed(self):
        self._settings.set_in_profile(
            f"{self.current_name}.filter_radius_{self.current_channel}",
            self.filter_radius.value())
        if self.use_filter.get_value() != NoiseFilterType.No:
            self.send_info()

    def gauss_use_changed(self):
        self._settings.set_in_profile(
            f"{self.current_name}.use_filter_{self.current_channel}",
            self.use_filter.get_value())
        if self.use_filter.get_value() == NoiseFilterType.Median:
            self.filter_radius.setDecimals(0)
            self.filter_radius.setSingleStep(1)
        else:
            self.filter_radius.setDecimals(2)
            self.filter_radius.setSingleStep(0.1)

        self.send_info()

    def lock_channel(self, value):
        self._settings.set_in_profile(
            f"{self.current_name}.lock_{self.current_channel}", value)
        self.send_info()

    def range_changed(self):
        self._settings.set_in_profile(
            f"{self.current_name}.range_{self.current_channel}",
            (self.minimum_value.value(), self.maximum_value.value()),
        )
        if self.fixed.isChecked():
            self.send_info()
Beispiel #25
0
class ShearMomentTorqueWindow(PyDialog):
    """
    +-------------------------+
    | ShearMomentTorqueWindow |
    +-------------------------+
    | Origin      cid  x y z  |
    | P2          cid  x y z  |
    | z-axis      cid  x y z  |
    | tol         cid  x y z  |
    |                         |
    |    Apply OK Cancel      |
    +-------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self._default_font_size = data['font_size']

        #self.dim_max = data['dim_max']
        self.model_name = data['model_name']
        self.cids = data['cids']
        self.gpforce = data['gpforce']
        #self._origin = data['origin']
        #self._p1 = data['origin']
        #self._p2 = data['origin']

        #self.out_data = data

        self.plane_color_float, self.plane_color_int = check_color(
            data['plane_color'])
        self.plane_opacity = data['plane_opacity']
        self.methods = ['Z-Axis Projection', 'CORD2R']
        self.zaxis_methods = ['Global Z', 'Camera Normal', 'Manual']
        self._zaxis_method = 0  # Global Z

        self.setWindowTitle('Shear, Moment, Torque')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        #self.on_gradient_scale()
        #self.show()

    def on_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)

    def set_font_size(self, font_size):
        """
        Updates the font size of all objects in the PyDialog

        Parameters
        ----------
        font_size : int
            the font size
        """
        if self.font_size == font_size:
            return
        self.font_size = font_size
        font = make_font(font_size, is_bold=False)
        self.setFont(font)
        self.set_bold_font(font_size)

    def set_bold_font(self, font_size):
        """
        Updates the font size of all bolded objects in the dialog

        Parameters
        ----------
        font_size : int
            the font size
        """
        bold_font = make_font(font_size, is_bold=True)

        self.additional_params_label.setFont(bold_font)
        self.case_info_label.setFont(bold_font)
        self.plane_label.setFont(bold_font)

        self.location_label.setFont(bold_font)
        self.cid_label.setFont(bold_font)
        self.x_label.setFont(bold_font)
        self.y_label.setFont(bold_font)
        self.z_label.setFont(bold_font)

    def create_widgets(self):
        """creates the display window"""

        # CORD2R
        #self.origin_label = QLabel("Origin:")
        #self.zaxis_label = QLabel("Z Axis:")
        #self.xz_plane_label = QLabel("XZ Plane:")

        # Z-Axis Projection
        self.p1_label = QLabel("Origin:")
        self.p3_label = QLabel("End:")
        self.p2_label = QLabel("XZ Plane:")
        self.p1_label.setToolTip('Defines the starting point for the shear, moment, torque plot')
        self.p3_label.setToolTip('Defines the end point for the shear, moment, torque plot')
        self.p2_label.setToolTip('Defines the XZ plane for the shears/moments')

        self.zaxis_label = QLabel("Z Axis:")

        self.method_pulldown = QComboBox()
        for method in self.methods:
            self.method_pulldown.addItem(method)

        self.zaxis_method_pulldown = QComboBox()
        for method in self.zaxis_methods:
            self.zaxis_method_pulldown.addItem(method)

        self.cid_label = QLabel("Coordinate System:")
        self.p1_cid_pulldown = QComboBox()
        self.p2_cid_pulldown = QComboBox()
        self.p3_cid_pulldown = QComboBox()
        self.zaxis_cid_pulldown = QComboBox()

        cid_global_str = '0/Global'
        for cid in sorted(self.cids):
            if cid == 0:
                cid_str = cid_global_str
            else:
                cid_str = str(cid)
            #print('cid_str = %r' % cid_str)
            self.p1_cid_pulldown.addItem(cid_str)
            self.p2_cid_pulldown.addItem(cid_str)
            self.p3_cid_pulldown.addItem(cid_str)
            self.zaxis_cid_pulldown.addItem(cid_str)

        self.p1_cid_pulldown.setCurrentIndex(0)
        self.p2_cid_pulldown.setCurrentIndex(0)
        self.p3_cid_pulldown.setCurrentIndex(0)
        self.zaxis_cid_pulldown.setCurrentIndex(0)
        if len(self.cids) == 1:
            self.p1_cid_pulldown.setEnabled(False)
            self.p2_cid_pulldown.setEnabled(False)
            self.p3_cid_pulldown.setEnabled(False)
            self.zaxis_cid_pulldown.setEnabled(False)

        #self.p1_cid_pulldown.setItemText(0, cid_str)
        #self.p2_cid_pulldown.setItemText(0, cid_str)
        #self.zaxis_cid_pulldown.setItemText(0, cid_str)

        self.p1_cid_pulldown.setToolTip('Defines the coordinate system for Point P1')
        self.p2_cid_pulldown.setToolTip('Defines the coordinate system for Point P2')
        self.p3_cid_pulldown.setToolTip('Defines the coordinate system for Point P3')
        self.zaxis_cid_pulldown.setToolTip('Defines the coordinate system for the Z Axis')

        self.p1_x_edit = QFloatEdit('')
        self.p1_y_edit = QFloatEdit('')
        self.p1_z_edit = QFloatEdit('')

        self.p2_x_edit = QFloatEdit('')
        self.p2_y_edit = QFloatEdit('')
        self.p2_z_edit = QFloatEdit('')

        self.p3_x_edit = QFloatEdit('')
        self.p3_y_edit = QFloatEdit('')
        self.p3_z_edit = QFloatEdit('')

        self.zaxis_x_edit = QFloatEdit('')
        self.zaxis_y_edit = QFloatEdit('')
        self.zaxis_z_edit = QFloatEdit('')

        self.additional_params_label = QLabel('Plane Parameters:')
        self.case_info_label = QLabel('Case Info:')

        self.p2_label = QLabel("XZ Plane:")

        # Plane Color
        self.plane_color_label = QLabel("Plane Color:")
        self.plane_color_edit = QPushButtonColor(self.plane_color_int)

        self.plane_opacity_label = QLabel("Plane Opacity:")
        self.plane_opacity_edit = QDoubleSpinBox()
        self.plane_opacity_edit.setRange(0.1, 1.0)
        self.plane_opacity_edit.setDecimals(1)
        self.plane_opacity_edit.setSingleStep(0.1)
        self.plane_opacity_edit.setValue(self.plane_opacity)

        self.flip_coord_label = QLabel("Flip Coordinate System:")
        self.flip_coord_checkbox = QCheckBox()

        #-----------------------------------------------------------------------
        self.time_label = QLabel('Time:')
        if self.gpforce is None:
            times = ['0.', '0.5', '1.' , '1.5', '2.']
            time = '0.'
        else:
            times = [func_str(time) for time in self.gpforce._times]
            time = times[0]
        self.times_pulldown = make_combo_box(times, time)
        self.time_label.setEnabled(False)
        self.times_pulldown.setEnabled(False)

        #self.node_label = QLabel('Nodes:')
        #self.node_edit = QNodeEdit(self.win_parent, self.model_name, parent=self.gui,
                                   #pick_style='area', tab_to_next=False)

        #self.element_label = QLabel('Elements:')
        #self.element_edit = QElementEdit(self.win_parent, self.model_name, parent=self.gui,
                                         #pick_style='area', tab_to_next=False)

        #self.node_element_label = QLabel('Nodes/Elements:')
        #self.node_element_edit = QLineEdit()
        #self.node_element_edit.setReadOnly(True)

        self.nplanes_label = QLabel('Num Planes:')
        self.nplanes_spinner = QSpinBox()
        self.nplanes_spinner.setMinimum(2)
        self.nplanes_spinner.setMaximum(500)
        self.nplanes_spinner.setValue(20)

        #-----------------------------------------------------------------------
        self.method_label = QLabel('Method:')
        self.plane_label = QLabel('Plane:')
        self.location_label = QLabel('Location:')
        self.zaxis_method_label = QLabel('Z-Axis Method:')
        self.cid_label = QLabel('Coordinate System:')
        self.x_label = QLabel('X')
        self.y_label = QLabel('Y')
        self.z_label = QLabel('Z')

        #self.location_label.setAlignment(Qt.AlignCenter)
        self.cid_label.setAlignment(Qt.AlignCenter)

        self.x_label.setAlignment(Qt.AlignCenter)
        self.y_label.setAlignment(Qt.AlignCenter)
        self.z_label.setAlignment(Qt.AlignCenter)

        self.export_checkbox = QCheckBox()
        self.csv_label = QLabel('CSV Filename:')
        self.csv_edit = QLineEdit()
        self.csv_button = QPushButton('Browse...')
        self.csv_label.setEnabled(False)
        self.csv_edit.setEnabled(False)
        self.csv_button.setEnabled(False)
        #-----------------------------------------------------------------------
        # nodes
        self.add_button = QPushButton('Add')
        self.remove_button = QPushButton('Remove')

        # elements
        self.add2_button = QPushButton('Add')
        self.remove2_button = QPushButton('Remove')
        #-----------------------------------------------------------------------
        # closing
        self.apply_button = QPushButton('Apply')
        self.cancel_button = QPushButton('Cancel')
        self.set_bold_font(self._default_font_size)

    @property
    def gui(self):
        if self.win_parent is None:
            return None
        return self.win_parent.parent.gui

    def create_layout(self):
        """sets up the window"""
        grid = self._make_grid_layout()

        #hbox_csv = QHBoxLayout()
        grid2 = QGridLayout()
        #irow = 0

        #grid2.addWidget(self.node_label, irow, 0)
        #grid2.addWidget(self.node_edit, irow, 1)
        #grid2.addWidget(self.add_button, irow, 2)
        #grid2.addWidget(self.remove_button, irow, 3)
        #irow += 1

        #grid2.addWidget(self.element_label, irow, 0)
        #grid2.addWidget(self.element_edit, irow, 1)
        #grid2.addWidget(self.add2_button, irow, 2)
        #grid2.addWidget(self.remove2_button, irow, 3)
        #irow += 1

        #grid2.addWidget(self.node_element_label, irow, 0)
        #grid2.addWidget(self.node_element_edit, irow, 1)
        #irow += 1

        hbox_csv = QHBoxLayout()
        hbox_csv.addWidget(self.export_checkbox)
        hbox_csv.addWidget(self.csv_label)
        hbox_csv.addWidget(self.csv_edit)
        hbox_csv.addWidget(self.csv_button)
        #----------------------------------------------

        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()

        vbox.addLayout(grid)
        vbox.addLayout(grid2)
        #vbox.addStretch()
        vbox.addLayout(hbox_csv)
        vbox.addStretch()

        #-----------------------
        #vbox.addLayout(add_remove_box)
        vbox.addLayout(ok_cancel_box)
        self.on_method(0)
        self.on_zaxis_method(0)
        self.setLayout(vbox)

    def on_export_checkbox(self):
        """this is called when the checkbox is clicked"""
        is_checked = self.export_checkbox.isChecked()
        self.csv_label.setEnabled(is_checked)
        self.csv_edit.setEnabled(is_checked)
        self.csv_button.setEnabled(is_checked)

    def on_browse_csv(self):
        """opens a file dialog"""
        default_dirname = os.getcwd()
        csv_filename, wildcard = save_file_dialog(
            self, 'Select the file name for export',
            default_dirname, wildcard_csv)
        if not csv_filename:
            return
        self.csv_edit.setText(csv_filename)

    def _make_grid_layout(self):
        """builds the QGridLayout"""
        grid = QGridLayout()
        irow = 0
        #-------------------------
        grid.addWidget(self.location_label, irow, 0)
        grid.addWidget(self.cid_label, irow, 1)
        grid.addWidget(self.x_label, irow, 2)
        grid.addWidget(self.y_label, irow, 3)
        grid.addWidget(self.z_label, irow, 4)
        irow += 1

        add_row(irow, grid,
                self.p1_label,
                self.p1_cid_pulldown,
                self.p1_x_edit, self.p1_y_edit, self.p1_z_edit)
        irow += 1

        add_row(irow, grid,
                self.p3_label,
                self.p3_cid_pulldown,
                self.p3_x_edit, self.p3_y_edit, self.p3_z_edit)
        irow += 1

        grid.addWidget(self.plane_label, irow, 0)
        irow += 1

        grid.addWidget(self.method_label, irow, 0)
        grid.addWidget(self.method_pulldown, irow, 1)
        irow += 1

        grid.addWidget(self.zaxis_method_label, irow, 0)
        grid.addWidget(self.zaxis_method_pulldown, irow, 1)
        irow += 1

        add_row(irow, grid,
                self.zaxis_label,
                self.zaxis_cid_pulldown,
                self.zaxis_x_edit, self.zaxis_y_edit, self.zaxis_z_edit)
        irow += 1

        add_row(irow, grid,
                self.p2_label,
                self.p2_cid_pulldown,
                self.p2_x_edit, self.p2_y_edit, self.p2_z_edit)
        irow += 1

        #-----------------------------------------
        grid.addWidget(self.case_info_label, irow, 0)
        irow += 1

        grid.addWidget(self.time_label, irow, 0)
        grid.addWidget(self.times_pulldown, irow, 1)
        irow += 1

        grid.addWidget(self.nplanes_label, irow, 0)
        grid.addWidget(self.nplanes_spinner, irow, 1)
        irow += 1

        #-----------------------------------------
        grid.addWidget(self.additional_params_label, irow, 0)
        irow += 1

        grid.addWidget(self.plane_color_label, irow, 0)
        grid.addWidget(self.plane_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.plane_opacity_label, irow, 0)
        grid.addWidget(self.plane_opacity_edit, irow, 1)
        irow += 1
        #----------------------------------------------
        return grid

    def set_connections(self):
        """creates the actions for the menu"""
        self.method_pulldown.currentIndexChanged.connect(self.on_method)
        self.zaxis_method_pulldown.currentIndexChanged.connect(self.on_zaxis_method)
        self.plane_color_edit.clicked.connect(self.on_plane_color)

        self.export_checkbox.clicked.connect(self.on_export_checkbox)
        self.csv_button.clicked.connect(self.on_browse_csv)

        self.apply_button.clicked.connect(self.on_apply)
        self.cancel_button.clicked.connect(self.on_cancel)

    def on_method(self, method_int=None):
        method = get_pulldown_text(method_int, self.methods, self.method_pulldown)
        if method == 'Z-Axis Projection':
            is_cord2r = False
        elif method == 'CORD2R':
            is_cord2r = True
        else:
            raise NotImplementedError(method)

        if is_cord2r:
            self._zaxis_method = self.zaxis_method_pulldown.currentIndex()
            # set to manual
            #self.on_zaxis_method(method_int=2)  # manual

            self.zaxis_method_pulldown.setCurrentIndex(2)
            self.on_zaxis_method()  # update
        else:
            self.zaxis_method_pulldown.setCurrentIndex(self._zaxis_method)
            self.on_zaxis_method()  # update

        # works
        self.zaxis_method_pulldown.setEnabled(not is_cord2r)
        self.zaxis_method_pulldown.setVisible(not is_cord2r)
        self.zaxis_method_label.setEnabled(not is_cord2r)

    def on_zaxis_method(self, method_int=None):
        method = get_pulldown_text(method_int, self.zaxis_methods, self.zaxis_method_pulldown)

        if method == 'Global Z':
            is_visible = False
        elif method == 'Camera Normal':
            is_visible = False
        elif method == 'Manual':
            is_visible = True
        else:
            raise NotImplementedError(method)

        self.zaxis_cid_pulldown.setVisible(is_visible)
        self.zaxis_x_edit.setVisible(is_visible)
        self.zaxis_y_edit.setVisible(is_visible)
        self.zaxis_z_edit.setVisible(is_visible)

    def on_plane_color(self):
        """ Choose a plane color"""
        title = "Choose a cutting plane color"
        rgb_color_ints = self.plane_color_int
        color_edit = self.plane_color_edit
        func_name = 'set_plane_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.plane_color_int = rgb_color_ints
            self.plane_color_float = rgb_color_floats

    def _background_color(self, title, color_edit, rgb_color_ints, func_name):
        """helper method for ``on_background_color`` and ``on_background_color2``"""
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            color_edit, rgb_color_ints, title)
        if passed and 0:
            if self.win_parent is not None:
                settings = self.win_parent.settings
                func_background_color = getattr(settings, func_name)
                func_background_color(rgb_color_floats)
        return passed, rgb_color_ints, rgb_color_floats

    def on_color(self, color_edit, rgb_color_ints, title):
        """pops a color dialog"""
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    title)
        if not col.isValid():
            return False, rgb_color_ints, None

        color_float = col.getRgbF()[:3]  # floats
        color_int = [int(colori * 255) for colori in color_float]

        assert isinstance(color_float[0], float), color_float
        assert isinstance(color_int[0], int), color_int

        color_edit.setStyleSheet(
            "QPushButton {"
            "background-color: rgb(%s, %s, %s);" % tuple(color_int) +
            #"border:1px solid rgb(255, 170, 255); "
            "}")
        return True, color_int, color_float


    #---------------------------------------------------------------------------

    def on_validate(self):
        p1_cidi = self.p1_cid_pulldown.currentText()
        p2_cidi = self.p2_cid_pulldown.currentText()
        p3_cidi = self.p3_cid_pulldown.currentText()
        zaxis_cidi = self.zaxis_cid_pulldown.currentText()
        p1_cid = int(p1_cidi) if 'Global' not in p1_cidi else 0
        p2_cid = int(p2_cidi) if 'Global' not in p2_cidi else 0
        p3_cid = int(p3_cidi) if 'Global' not in p3_cidi else 0
        zaxis_cid = int(zaxis_cidi) if 'Global' not in zaxis_cidi else 0
        #print('p1_cidi=%r p2_cidi=%r p3_cidi=%r' % (p1_cidi, p2_cidi, zaxis_cidi))
        #print('p2_cid=%r p2_cid=%r p3_cidi=%r' % (p2_cid, p2_cid, zaxis_cid))

        p1_x, flag1 = check_float(self.p1_x_edit)
        p1_y, flag2 = check_float(self.p1_y_edit)
        p1_z, flag3 = check_float(self.p1_z_edit)

        p2_x, flag4 = check_float(self.p2_x_edit)
        p2_y, flag5 = check_float(self.p2_y_edit)
        p2_z, flag6 = check_float(self.p2_z_edit)

        p3_x, flag7 = check_float(self.p3_x_edit)
        p3_y, flag8 = check_float(self.p3_y_edit)
        p3_z, flag9 = check_float(self.p3_z_edit)
        p1 = [p1_x, p1_y, p1_z]
        p2 = [p2_x, p2_y, p2_z]
        p3 = [p3_x, p3_y, p3_z]

        flag10, flag11, flag12, zaxis_cid, zaxis = get_zaxis(
            self.win_parent, # for camera
            self.zaxis_method_pulldown,
            self.zaxis_x_edit, self.zaxis_y_edit, self.zaxis_z_edit)

        method = self.method_pulldown.currentText()
        assert method in self.methods, 'method=%r' % method
        flag13 = True

        plane_opacity = self.plane_opacity_edit.value()
        nplanes = self.nplanes_spinner.value()

        csv_filename = None
        flag14 = True
        if self.export_checkbox.isChecked():
            csv_filename, flag14 = check_save_path(self.csv_edit)

        flags = [flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, flag9,
                 flag10, flag11, flag12,
                 flag13, flag14]
        if all(flags):
            # Z-Axis Method
            # p1: origin
            # p2: xz_plane
            # p3: end
            self.out_data['method'] = method
            self.out_data['p1'] = [p1_cid, p1]  # origin
            self.out_data['p2'] = [p2_cid, p2]  # xzplane
            self.out_data['p3'] = [p3_cid, p3]  # end
            self.out_data['zaxis'] = [zaxis_cid, zaxis]
            self.out_data['plane_color'] = self.plane_color_float
            self.out_data['plane_opacity'] = plane_opacity
            self.out_data['nplanes'] = nplanes
            self.out_data['csv_filename'] = csv_filename
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self):
        passed = self.on_validate()
        if passed and self.win_parent is not None:
            self.win_parent.shear_moment_torque_obj.make_smt_from_data(self.out_data, show=True)
            #self.win_parent.make_smt_from_data(self.out_data)
        return passed

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
Beispiel #26
0
class QtVectorsControls(QtLayerControls):
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.edge_width.connect(self._on_width_change)
        self.layer.events.length.connect(self._on_len_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)

        # vector color adjustment and widget
        edge_comboBox = QComboBox()
        edge_comboBox.addItems(self.layer._colors)
        edge_comboBox.activated[str].connect(self.change_edge_color)
        self.edgeComboBox = edge_comboBox
        self.edgeColorSwatch = QFrame()
        self.edgeColorSwatch.setObjectName('swatch')
        self.edgeColorSwatch.setToolTip('Edge color swatch')
        self._on_edge_color_change()

        # line width in pixels
        self.widthSpinBox = QDoubleSpinBox()
        self.widthSpinBox.setKeyboardTracking(False)
        self.widthSpinBox.setSingleStep(0.1)
        self.widthSpinBox.setMinimum(0.1)
        self.widthSpinBox.setValue(self.layer.edge_width)
        self.widthSpinBox.valueChanged.connect(self.change_width)

        # line length
        self.lengthSpinBox = QDoubleSpinBox()
        self.lengthSpinBox.setKeyboardTracking(False)
        self.lengthSpinBox.setSingleStep(0.1)
        self.lengthSpinBox.setValue(self.layer.length)
        self.lengthSpinBox.setMinimum(0.1)
        self.lengthSpinBox.valueChanged.connect(self.change_length)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addWidget(QLabel('opacity:'), 0, 0)
        self.grid_layout.addWidget(self.opacitySlider, 0, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('width:'), 1, 0)
        self.grid_layout.addWidget(self.widthSpinBox, 1, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('length:'), 2, 0)
        self.grid_layout.addWidget(self.lengthSpinBox, 2, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('blending:'), 3, 0)
        self.grid_layout.addWidget(self.blendComboBox, 3, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('edge color:'), 4, 0)
        self.grid_layout.addWidget(self.edgeComboBox, 4, 2)
        self.grid_layout.addWidget(self.edgeColorSwatch, 4, 1)
        self.grid_layout.setRowStretch(5, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def change_edge_color(self, text):
        self.layer.edge_color = text

    def change_width(self, value):
        self.layer.edge_width = value
        self.widthSpinBox.clearFocus()
        self.setFocus()

    def change_length(self, value):
        self.layer.length = value
        self.lengthSpinBox.clearFocus()
        self.setFocus()

    def _on_len_change(self, event=None):
        with self.layer.events.length.blocker():
            self.lengthSpinBox.setValue(self.layer.length)

    def _on_width_change(self, event=None):
        with self.layer.events.edge_width.blocker():
            self.widthSpinBox.setValue(self.layer.edge_width)

    def _on_edge_color_change(self, event=None):
        with self.layer.events.edge_color.blocker():
            index = self.edgeComboBox.findText(self.layer.edge_color,
                                               Qt.MatchFixedString)
            self.edgeComboBox.setCurrentIndex(index)
        color = Color(self.layer.edge_color).hex
        self.edgeColorSwatch.setStyleSheet("background-color: " + color)
Beispiel #27
0
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self.dim_max = data['dim_max']

        # font size for menu
        self._default_font_size = FONT_SIZE
        self._default_text_size = TEXT_SIZE

        # an annotation is the marked/probe label
        self._default_annotation_size = ANNOTATION_SIZE

        self._default_coord_scale = COORD_SCALE * 100. # * self.dim_max
        self._default_coord_text_scale = COORD_TEXT_SCALE * 100. # * self.dim_max
        self._default_clipping_min = data['min_clip']
        self._default_clipping_max = data['max_clip']
        #self._default_annotation_size = data['annotation_size'] # int
        #self.default_magnify = data['magnify']

        self._use_gradient_background = data['use_gradient_background'] # bool
        self._show_corner_coord = data['show_corner_coord']
        self._annotation_size = data['annotation_size'] # int

        #self.out_data = data

        # doesn't include dim_max
        self._picker_size = data['picker_size'] * 100.
        self._coord_scale = data['coord_scale'] * 100.
        self._coord_text_scale = data['coord_text_scale'] * 100.

        self._magnify = data['magnify']
        self._text_size = data['text_size']
        self._highlight_opacity = data['highlight_opacity']

        self.annotation_color_float, self.annotation_color_int = check_color(
            data['annotation_color'])
        self.background_color_float, self.background_color_int = check_color(
            data['background_color'])
        self.background_color2_float, self.background_color2_int = check_color(
            data['background_color2'])
        self.text_color_float, self.text_color_int = check_color(
            data['text_color'])
        self.highlight_color_float, self.highlight_color_int = check_color(
            data['highlight_color'])

        self._nastran_is_element_quality = data['nastran_is_element_quality']
        self._nastran_is_properties = data['nastran_is_properties']
        self._nastran_is_3d_bars = data['nastran_is_3d_bars']
        self._nastran_is_3d_bars_update = data['nastran_is_3d_bars_update']
        self._nastran_is_bar_axes = data['nastran_is_bar_axes']
        self._nastran_create_coords = data['nastran_create_coords']
        self._nastran_is_shell_mcids = data['nastran_is_shell_mcids']

        self._nastran_stress = data['nastran_stress']
        self._nastran_plate_stress = data['nastran_plate_stress']
        self._nastran_composite_plate_stress = data['nastran_composite_plate_stress']
        self._nastran_strain = data['nastran_strain']
        self._nastran_plate_strain = data['nastran_plate_strain']
        self._nastran_composite_plate_strain = data['nastran_composite_plate_strain']
        self._nastran_rod_stress = data['nastran_rod_stress']
        self._nastran_bar_stress = data['nastran_bar_stress']
        self._nastran_beam_stress = data['nastran_beam_stress']
        self._nastran_rod_strain = data['nastran_rod_strain']
        self._nastran_bar_strain = data['nastran_bar_strain']
        self._nastran_beam_strain = data['nastran_beam_strain']


        self.setWindowTitle('Preferences')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        self.on_gradient_scale()
        #self.show()

    def create_widgets(self):
        """creates the display window"""
        # Text Size
        self.font_size_label = QLabel("Font Size:")
        self.font_size_edit = QSpinBox(self)
        self.font_size_edit.setValue(self._default_font_size)
        self.font_size_edit.setRange(7, 20)
        self.font_size_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # Annotation Color
        self.annotation_color_label = QLabel("Annotation Color:")
        self.annotation_color_edit = QPushButtonColor(self.annotation_color_int)
        self.annotation_color_label.hide()
        self.annotation_color_edit.hide()
        #-----------------------------------------------------------------------
        # Text Color
        self.text_size_label = QLabel("Text Size:")
        self.text_size_edit = QSpinBox(self)
        self.text_size_edit.setValue(self._default_text_size)
        self.text_size_edit.setRange(7, 30)
        self.text_size_button = QPushButton("Default")

        # Text Color
        self.text_color_label = QLabel("Text Color:")
        self.text_color_edit = QPushButtonColor(self.text_color_int)

        #-----------------------------------------------------------------------
        # Highlight Color
        self.highlight_opacity_label = QLabel("Highlight Opacity:")
        self.highlight_opacity_edit = QDoubleSpinBox(self)
        self.highlight_opacity_edit.setValue(self._highlight_opacity)
        self.highlight_opacity_edit.setRange(0.1, 1.0)
        self.highlight_opacity_edit.setDecimals(1)
        self.highlight_opacity_edit.setSingleStep(0.1)
        self.highlight_opacity_button = QPushButton("Default")

        # Text Color
        self.highlight_color_label = QLabel("Highlight Color:")
        self.highlight_color_edit = QPushButtonColor(self.highlight_color_int)

        #-----------------------------------------------------------------------
        # Background Color
        self.background_color_label = QLabel("Btm Background Color:")
        self.background_color_edit = QPushButtonColor(self.background_color_int)

        # Background Color2
        self.gradient_scale_label = QLabel("Gradient Background:")
        self.gradient_scale_checkbox = QCheckBox()
        self.gradient_scale_checkbox.setChecked(self._use_gradient_background)

        self.background_color2_label = QLabel("Top Background Color:")
        self.background_color2_edit = QPushButtonColor(self.background_color2_int)

        #-----------------------------------------------------------------------
        # Annotation Size
        self.annotation_size_label = QLabel("Annotation Size:")
        self.annotation_size_edit = QSpinBox(self)
        self.annotation_size_edit.setRange(1, 500)
        self.annotation_size_edit.setValue(self._annotation_size)
        self.annotation_size_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        # Picker Size
        self.picker_size_label = QLabel("Picker Size (% of Screen):")
        self.picker_size_edit = QDoubleSpinBox(self)
        self.picker_size_edit.setRange(0., 10.)

        log_dim = log10(self.dim_max)
        decimals = int(ceil(abs(log_dim)))

        decimals = max(6, decimals)
        self.picker_size_edit.setDecimals(decimals)
        self.picker_size_edit.setSingleStep(10. / 5000.)
        self.picker_size_edit.setValue(self._picker_size)

        #-----------------------------------------------------------------------
        # Clipping Min
        self.clipping_min_label = QLabel("Clipping Min:")
        self.clipping_min_edit = QLineEdit(str(self._default_clipping_min))
        self.clipping_min_button = QPushButton("Default")

        # Clipping Max
        self.clipping_max_label = QLabel("Clipping Max:")
        self.clipping_max_edit = QLineEdit(str(self._default_clipping_max))
        self.clipping_max_button = QPushButton("Default")

        #-----------------------------------------------------------------------
        self.coord_scale_label = QLabel('Coordinate System Scale:')
        self.coord_scale_button = QPushButton("Default")

        self.coord_scale_edit = QDoubleSpinBox(self)
        self.coord_scale_edit.setRange(0.1, 1000.)
        self.coord_scale_edit.setDecimals(3)
        self.coord_scale_edit.setSingleStep(1.0)
        self.coord_scale_edit.setValue(self._coord_scale)

        self.coord_text_scale_label = QLabel('Coordinate System Text Scale:')
        self.coord_text_scale_button = QPushButton("Default")

        self.coord_text_scale_edit = QDoubleSpinBox(self)
        self.coord_text_scale_edit.setRange(0.1, 2000.)
        self.coord_text_scale_edit.setDecimals(3)
        self.coord_text_scale_edit.setSingleStep(2.)
        self.coord_text_scale_edit.setValue(self._coord_text_scale)

        # Show corner coord
        self.corner_coord_label = QLabel("Show Corner Coordinate System:")
        self.corner_coord_checkbox = QCheckBox()
        self.corner_coord_checkbox.setChecked(self._show_corner_coord)

        #-----------------------------------------------------------------------
        self.magnify_label = QLabel('Screenshot Magnify:')
        self.magnify_edit = QSpinBox(self)
        self.magnify_edit.setMinimum(1)
        self.magnify_edit.setMaximum(10)
        self.magnify_edit.setValue(self._magnify)

        #-----------------------------------------------------------------------
        self.nastran_is_element_quality_checkbox = QCheckBox('Element Quality')
        self.nastran_is_element_quality_checkbox.setToolTip('Cacluate Aspect Ratio, Skew Angle, Max/Min Interior Angle, etc.')
        self.nastran_is_element_quality_checkbox.setChecked(self._nastran_is_element_quality)

        self.nastran_is_properties_checkbox = QCheckBox('Properties')
        self.nastran_is_properties_checkbox.setToolTip('Breakdown each layer of a PCOMP/PSHELL')
        self.nastran_is_properties_checkbox.setChecked(self._nastran_is_properties)

        self.nastran_is_3d_bars_checkbox = QCheckBox('3D Bars')
        self.nastran_is_3d_bars_checkbox.setToolTip('Crete 3D Bar/Beam geometry')
        self.nastran_is_3d_bars_checkbox.setChecked(self._nastran_is_3d_bars)
        #self.nastran_is_3d_bars_checkbox.setDisabled(True)

        self.nastran_is_3d_bars_update_checkbox = QCheckBox('Update 3D Bars')
        self.nastran_is_3d_bars_update_checkbox.setToolTip('Update the 3D Bar/Beam cross-sections when deformations are applied')
        self.nastran_is_3d_bars_update_checkbox.setChecked(self._nastran_is_3d_bars_update)

        self.nastran_is_shell_mcid_checkbox = QCheckBox('Shell MCIDs')
        self.nastran_is_shell_mcid_checkbox.setToolTip('Calculate the Material Coordinate Systems for Shells')
        self.nastran_is_shell_mcid_checkbox.setChecked(self._nastran_is_shell_mcids)

        self.nastran_create_coords_checkbox = QCheckBox('Coords')
        self.nastran_create_coords_checkbox.setChecked(self._nastran_create_coords)

        self.nastran_is_bar_axes_checkbox = QCheckBox('Bar Axes')
        self.nastran_is_bar_axes_checkbox.setChecked(self._nastran_is_bar_axes)
        #self.nastran_is_bar_axes_checkbox.setDisabled(True)

        if 0:
            self.nastran_stress_checkbox = QCheckBox('Stress')
            self.nastran_plate_stress_checkbox = QCheckBox('Plate Stress')
            self.nastran_composite_plate_stress_checkbox = QCheckBox('Composite Plate Stress')
            self.nastran_rod_stress_checkbox = QCheckBox('Rod Stress')
            self.nastran_bar_stress_checkbox = QCheckBox('Bar Stress')
            self.nastran_beam_stress_checkbox = QCheckBox('Beam Stress')

            self.nastran_stress_checkbox.setChecked(self._nastran_stress)
            self.nastran_plate_stress_checkbox.setChecked(self._nastran_plate_stress)
            self.nastran_composite_plate_stress_checkbox.setChecked(self._nastran_composite_plate_stress)
            self.nastran_rod_stress_checkbox.setChecked(self._nastran_rod_stress)
            self.nastran_bar_stress_checkbox.setChecked(self._nastran_bar_stress)
            self.nastran_beam_stress_checkbox.setChecked(self._nastran_beam_stress)

            self.nastran_strain_checkbox = QCheckBox('Strain')
            self.nastran_plate_strain_checkbox = QCheckBox('Plate Strain')
            self.nastran_composite_plate_strain_checkbox = QCheckBox('Composite Plate Strain')
            self.nastran_rod_strain_checkbox = QCheckBox('Rod Strain')
            self.nastran_bar_strain_checkbox = QCheckBox('Bar Strain')
            self.nastran_beam_strain_checkbox = QCheckBox('Beam Strain')

            self.nastran_strain_checkbox.setChecked(self._nastran_strain)
            self.nastran_plate_strain_checkbox.setChecked(self._nastran_plate_strain)
            self.nastran_composite_plate_strain_checkbox.setChecked(self._nastran_composite_plate_strain)
            self.nastran_rod_strain_checkbox.setChecked(self._nastran_rod_strain)
            self.nastran_bar_strain_checkbox.setChecked(self._nastran_bar_strain)
            self.nastran_beam_strain_checkbox.setChecked(self._nastran_beam_strain)

        #-----------------------------------------------------------------------
        # closing
        self.apply_button = QPushButton("Apply")
        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

    #def create_legend_widgets(self):
        #"""
        #Creates the widgets for the legend control

        #Name    Itailic  Bold     Font
        #====    =======  =====  ========
        #Title    check   check  pulldown
        #Label    check   check  pulldown
        #"""
        #self.name_label = QLabel("Name:")
        #self.italic_label = QLabel("Italic:")
        #self.bold_label = QLabel("Bold:")
        #self.font_label = QLabel("Font:")
        #self.legend_label = QLabel("Legend:")

        #self.legend_title_name = QLabel("Title")
        #self.legend_title_italic_check = QCheckBox()
        #self.legend_title_bold_check = QCheckBox()
        #self.legend_title_font_edit = QComboBox()
        #self.legend_title_font_edit.addItems(['cat', 'dog', 'frog'])

        #self.legend_label_italic_name = QLabel("Label")
        #self.legend_label_italic_check = QCheckBox()
        #self.legend_label_bold_check = QCheckBox()
        #self.legend_label_font_edit = QComboBox()
        #self.legend_label_font_edit.addItems(['cat2', 'dog2', 'frog2'])

    #def create_legend_layout(self):
        #"""
        #Creates the layout for the legend control

        #Name    Italic  Bold     Font
        #====    ======  =====  ========
        #Title    check  check  pulldown
        #Label    check  check  pulldown
        #"""
        #grid2 = QGridLayout()
        #grid2.addWidget(self.legend_label, 0, 0)

        #grid2.addWidget(self.name_label, 1, 0)
        #grid2.addWidget(self.italic_label, 1, 1)
        #grid2.addWidget(self.bold_label, 1, 2)
        #grid2.addWidget(self.font_label, 1, 3)

        #grid2.addWidget(self.legend_title_name, 2, 0)
        #grid2.addWidget(self.legend_title_italic_check, 2, 1)
        #grid2.addWidget(self.legend_title_bold_check, 2, 2)
        #grid2.addWidget(self.legend_title_font_edit, 2, 3)

        #grid2.addWidget(self.legend_label_italic_name, 3, 0)
        #grid2.addWidget(self.legend_label_italic_check, 3, 1)
        #grid2.addWidget(self.legend_label_bold_check, 3, 2)
        #grid2.addWidget(self.legend_label_font_edit, 3, 3)
        #return grid2

    def create_layout(self):
        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.font_size_label, irow, 0)
        grid.addWidget(self.font_size_edit, irow, 1)
        grid.addWidget(self.font_size_button, irow, 2)
        irow += 1

        grid.addWidget(self.gradient_scale_label, irow, 0)
        grid.addWidget(self.gradient_scale_checkbox, irow, 1)
        irow += 1

        grid.addWidget(self.background_color2_label, irow, 0)
        grid.addWidget(self.background_color2_edit, irow, 1)
        irow += 1

        grid.addWidget(self.background_color_label, irow, 0)
        grid.addWidget(self.background_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.highlight_color_label, irow, 0)
        grid.addWidget(self.highlight_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.highlight_opacity_label, irow, 0)
        grid.addWidget(self.highlight_opacity_edit, irow, 1)
        irow += 1

        grid.addWidget(self.text_color_label, irow, 0)
        grid.addWidget(self.text_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.text_size_label, irow, 0)
        grid.addWidget(self.text_size_edit, irow, 1)
        grid.addWidget(self.text_size_button, irow, 2)
        irow += 1

        grid.addWidget(self.annotation_color_label, irow, 0)
        grid.addWidget(self.annotation_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.annotation_size_label, irow, 0)
        grid.addWidget(self.annotation_size_edit, irow, 1)
        grid.addWidget(self.annotation_size_button, irow, 2)
        irow += 1

        #grid.addWidget(self.clipping_min_label, irow, 0)
        #grid.addWidget(self.clipping_min_edit, irow, 1)
        #grid.addWidget(self.clipping_min_button, irow, 2)
        #irow += 1

        #grid.addWidget(self.clipping_max_label, irow, 0)
        #grid.addWidget(self.clipping_max_edit, irow, 1)
        #grid.addWidget(self.clipping_max_button, irow, 2)
        #irow += 1

        grid.addWidget(self.corner_coord_label, irow, 0)
        grid.addWidget(self.corner_coord_checkbox, irow, 1)
        irow += 1

        grid.addWidget(self.coord_scale_label, irow, 0)
        grid.addWidget(self.coord_scale_edit, irow, 1)
        grid.addWidget(self.coord_scale_button, irow, 2)
        irow += 1

        grid.addWidget(self.coord_text_scale_label, irow, 0)
        grid.addWidget(self.coord_text_scale_edit, irow, 1)
        grid.addWidget(self.coord_text_scale_button, irow, 2)
        irow += 1

        #-----------------------------------------------
        grid.addWidget(self.magnify_label, irow, 0)
        grid.addWidget(self.magnify_edit, irow, 1)
        irow += 1

        grid.addWidget(self.picker_size_label, irow, 0)
        grid.addWidget(self.picker_size_edit, irow, 1)
        irow += 1

        #--------------------------------------------------
        grid_nastran = QGridLayout()
        irow = 0

        grid_nastran.addWidget(self.nastran_create_coords_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_element_quality_checkbox, irow, 0)
        grid_nastran.addWidget(self.nastran_is_properties_checkbox, irow, 1)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_bar_axes_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_shell_mcid_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_3d_bars_checkbox, irow, 0)
        grid_nastran.addWidget(self.nastran_is_3d_bars_update_checkbox, irow, 1)
        irow += 1

        #bold_font = make_font(self._default_font_size, is_bold=True)
        vbox_nastran = QVBoxLayout()
        self.nastran_label = QLabel('Nastran:')
        vbox_nastran.addWidget(self.nastran_label)
        vbox_nastran.addLayout(grid_nastran)

        #self.create_legend_widgets()
        #grid2 = self.create_legend_layout()
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.apply_button)
        ok_cancel_box.addWidget(self.ok_button)
        ok_cancel_box.addWidget(self.cancel_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        vbox.addLayout(vbox_nastran)
        #vbox.addStretch()
        #vbox.addLayout(grid2)
        vbox.addStretch()

        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        self.font_size_button.clicked.connect(self.on_default_font_size)
        self.font_size_edit.valueChanged.connect(self.on_font)

        self.annotation_size_edit.editingFinished.connect(self.on_annotation_size)
        self.annotation_size_edit.valueChanged.connect(self.on_annotation_size)
        self.annotation_color_edit.clicked.connect(self.on_annotation_color)
        self.annotation_size_button.clicked.connect(self.on_default_annotation_size)

        self.background_color_edit.clicked.connect(self.on_background_color)
        self.background_color2_edit.clicked.connect(self.on_background_color2)
        self.gradient_scale_checkbox.clicked.connect(self.on_gradient_scale)

        self.highlight_color_edit.clicked.connect(self.on_highlight_color)
        self.highlight_opacity_edit.valueChanged.connect(self.on_highlight_opacity)

        self.text_color_edit.clicked.connect(self.on_text_color)
        self.text_size_edit.valueChanged.connect(self.on_text_size)
        self.text_size_button.clicked.connect(self.on_default_text_size)

        self.picker_size_edit.valueChanged.connect(self.on_picker_size)
        self.picker_size_edit.editingFinished.connect(self.on_picker_size)

        self.coord_scale_edit.valueChanged.connect(self.on_coord_scale)
        self.coord_scale_edit.editingFinished.connect(self.on_coord_scale)
        self.coord_scale_button.clicked.connect(self.on_default_coord_scale)
        self.corner_coord_checkbox.clicked.connect(self.on_corner_coord)

        self.coord_text_scale_edit.valueChanged.connect(self.on_coord_text_scale)
        self.coord_text_scale_edit.editingFinished.connect(self.on_coord_text_scale)
        self.coord_text_scale_button.clicked.connect(self.on_default_coord_text_scale)

        self.magnify_edit.valueChanged.connect(self.on_magnify)
        self.magnify_edit.editingFinished.connect(self.on_magnify)

        self.clipping_min_button.clicked.connect(self.on_default_clipping_min)
        self.clipping_max_button.clicked.connect(self.on_default_clipping_max)

        #------------------------------------
        # format-specific
        self.nastran_is_element_quality_checkbox.clicked.connect(self.on_nastran_is_element_quality)
        self.nastran_is_properties_checkbox.clicked.connect(self.on_nastran_is_properties)
        self.nastran_is_3d_bars_checkbox.clicked.connect(self.on_nastran_is_3d_bars)
        self.nastran_is_3d_bars_update_checkbox.clicked.connect(self.on_nastran_is_3d_bars_update)
        self.nastran_is_bar_axes_checkbox.clicked.connect(self.on_nastran_is_bar_axes)
        self.nastran_create_coords_checkbox.clicked.connect(self.on_nastran_create_coords)
        self.nastran_is_shell_mcid_checkbox.clicked.connect(self.on_nastran_is_shell_mcids)

        #self.nastran_is_shell_mcid_checkbox.clicked.connect(self.on_nastran_is_shell_mcids2)
        #------------------------------------

        self.apply_button.clicked.connect(self.on_apply)
        self.ok_button.clicked.connect(self.on_ok)
        self.cancel_button.clicked.connect(self.on_cancel)
        # closeEvent

    def on_nastran_is_element_quality(self):
        """set the nastran element quality preferences"""
        is_checked = self.nastran_is_element_quality_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_element_quality = is_checked
    def on_nastran_is_properties(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_properties_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_properties = is_checked
    def on_nastran_is_3d_bars(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_3d_bars_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_3d_bars = is_checked
    def on_nastran_is_3d_bars_update(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_3d_bars_update_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_3d_bars_update = is_checked
    def on_nastran_is_bar_axes(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_bar_axes_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_bar_axes = is_checked
    def on_nastran_create_coords(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_create_coords_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_create_coords = is_checked
    def on_nastran_is_shell_mcids(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_shell_mcid_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_shell_mcids = is_checked

    #def on_nastran_is_shell_mcids2(self):
        #"""set the nastran properties preferences"""
        #is_checked = self.nastran_is_shell_mcid_checkbox.isChecked()
        #if self.win_parent is not None:
            #self.win_parent.settings.nastran_is_shell_mcids = is_checked

    def on_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)
        bold_font = make_font(value, is_bold=True)
        self.nastran_label.setFont(bold_font)

    def on_annotation_size(self, value=None):
        """update the annotation size"""
        if value is None:
            value = int(self.annotation_size_edit.text())
        self._annotation_size = value
        #self.on_apply(force=True)
        #self.min_edit.setText(str(self._default_min))
        #self.min_edit.setStyleSheet("QLineEdit{background: white;}")
        self.update_annotation_size_color()

    def update_annotation_size_color(self):
        if self.win_parent is not None:
            self.win_parent.settings.set_annotation_size_color(size=self._annotation_size)

    def on_gradient_scale(self):
        is_checked = self.gradient_scale_checkbox.isChecked()
        self.background_color2_label.setEnabled(is_checked)
        self.background_color2_edit.setEnabled(is_checked)
        if self.win_parent is not None:
            self.win_parent.settings.set_gradient_background(use_gradient_background=is_checked)

    def on_corner_coord(self):
        is_checked = self.corner_coord_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.set_corner_axis_visiblity(is_checked, render=True)

    def on_annotation_color(self):
        rgb_color_ints = self.annotation_color_int
        title = "Choose an annotation color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.annotation_color_edit, rgb_color_ints, title)
        if passed:
            self.annotation_color_int = rgb_color_ints
            self.annotation_color_float = rgb_color_floats
            self.update_annotation_size_color()

    def on_background_color(self):
        """ Choose a background color"""
        title = "Choose a primary background color"
        rgb_color_ints = self.background_color_int
        color_edit = self.background_color_edit
        func_name = 'set_background_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.background_color_int = rgb_color_ints
            self.background_color_float = rgb_color_floats

    def on_background_color2(self):
        """ Choose a background color"""
        title = "Choose a secondary background color"
        rgb_color_ints = self.background_color2_int
        color_edit = self.background_color2_edit
        func_name = 'set_background_color2'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.background_color2_int = rgb_color_ints
            self.background_color2_float = rgb_color_floats

    def on_highlight_color(self):
        """ Choose a highlight color"""
        title = "Choose a highlight color"
        rgb_color_ints = self.highlight_color_int
        color_edit = self.highlight_color_edit
        func_name = 'set_highlight_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.highlight_color_int = rgb_color_ints
            self.highlight_color_float = rgb_color_floats

    def on_highlight_opacity(self, value=None):
        if value is None:
            value = self.highlight_opacity_edit.value()
        self._highlight_opacity = value
        if self.win_parent is not None:
            self.win_parent.settings.set_highlight_opacity(value)

    def _background_color(self, title, color_edit, rgb_color_ints, func_name):
        """helper method for ``on_background_color`` and ``on_background_color2``"""
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            color_edit, rgb_color_ints, title)
        if passed:
            if self.win_parent is not None:
                settings = self.win_parent.settings
                func_background_color = getattr(settings, func_name)
                func_background_color(rgb_color_floats)
        return passed, rgb_color_ints, rgb_color_floats

    def on_text_color(self):
        """Choose a text color"""
        rgb_color_ints = self.text_color_int
        title = "Choose a text color"
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            self.text_color_edit, rgb_color_ints, title)
        if passed:
            self.text_color_int = rgb_color_ints
            self.text_color_float = rgb_color_floats
            if self.win_parent is not None:
                self.win_parent.settings.set_text_color(rgb_color_floats)

    def on_default_text_size(self):
        self.text_size_edit.setValue(self._default_text_size)
        self.on_text_size(self._default_text_size)

    def on_text_size(self, value=None):
        if value is None:
            value = self.text_size_edit.value()
        self._text_size = value
        if self.win_parent is not None:
            self.win_parent.settings.set_text_size(value)

    def on_color(self, color_edit, rgb_color_ints, title):
        """pops a color dialog"""
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self,
                                    title)
        if not col.isValid():
            return False, rgb_color_ints, None

        color_float = col.getRgbF()[:3]  # floats
        color_int = [int(colori * 255) for colori in color_float]

        assert isinstance(color_float[0], float), color_float
        assert isinstance(color_int[0], int), color_int

        color_edit.setStyleSheet(
            "QPushButton {"
            "background-color: rgb(%s, %s, %s);" % tuple(color_int) +
            #"border:1px solid rgb(255, 170, 255); "
            "}")
        return True, color_int, color_float

    def on_picker_size(self):
        self._picker_size = float(self.picker_size_edit.text())
        if self.win_parent is not None:
            self.win_parent.element_picker_size = self._picker_size / 100.
        #self.on_apply(force=True)

    def on_magnify(self, value=None):
        if value is None:
            value = self.magnify_edit.value()
        self._magnify = value
        if self.win_parent is not None:
            self.win_parent.settings.set_magnify(value)

    #---------------------------------------------------------------------------
    def on_coord_scale(self, value=None):
        if value is None:
            value = self.coord_scale_edit.value()
        self._coord_scale = value
        if self.win_parent is not None:
            self.win_parent.settings.set_coord_scale(value / 100.)

    def on_default_coord_scale(self):
        self.coord_scale_edit.setValue(self._default_coord_scale)
        self.on_coord_scale(self._default_coord_scale)

    def on_coord_text_scale(self, value=None):
        if value is None:
            value = self.coord_text_scale_edit.value()
        self._coord_text_scale = value
        if self.win_parent is not None:
            self.win_parent.settings.set_coord_text_scale(value / 100.)

    def on_default_coord_text_scale(self):
        self.coord_text_scale_edit.setValue(self._default_coord_text_scale)
        self.on_coord_text_scale(self._default_coord_text_scale)

    #---------------------------------------------------------------------------
    def on_default_font_size(self):
        self.font_size_edit.setValue(self._default_font_size)
        self.on_font(self._default_font_size)

    def on_default_annotation_size(self):
        self.annotation_size_edit.setValue(self._default_annotation_size)
        self.on_annotation_size(self._default_annotation_size)

    def on_default_clipping_min(self):
        self.clipping_min_edit.setText(str(self._default_clipping_min))
        self.clipping_min_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_default_clipping_max(self):
        self.clipping_max_edit.setText(str(self._default_clipping_max))
        self.clipping_max_edit.setStyleSheet("QLineEdit{background: white;}")

    def on_validate(self):
        font_size_value, flag0 = check_float(self.font_size_edit)
        annotation_size_value, flag1 = check_float(self.annotation_size_edit)
        assert isinstance(self.annotation_color_float[0], float), self.annotation_color_float
        assert isinstance(self.annotation_color_int[0], int), self.annotation_color_int
        picker_size_value, flag2 = check_float(self.picker_size_edit)

        clipping_min_value, flag3 = check_label_float(self.clipping_min_edit)
        clipping_max_value, flag4 = check_label_float(self.clipping_max_edit)

        if all([flag0, flag1, flag2, flag3, flag4]):
            self._annotation_size = annotation_size_value
            self._picker_size = picker_size_value

            self.out_data['font_size'] = int(font_size_value)
            self.out_data['min_clip'] = min(clipping_min_value, clipping_max_value)
            self.out_data['max_clip'] = max(clipping_min_value, clipping_max_value)
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self, force=False):
        passed = self.on_validate()

        if (passed or force) and self.win_parent is not None:
            self.win_parent.settings.on_set_font_size(self.out_data['font_size'])

            #self.win_parent.settings.set_annotation_size_color(self._annotation_size)
            #self.win_parent.element_picker_size = self._picker_size / 100.
        if passed and self.win_parent is not None:
            self.win_parent.clipping_obj.apply_clipping(self.out_data)
        return passed

    def on_ok(self):
        passed = self.on_apply()
        if passed:
            self.close()
            #self.destroy()

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
Beispiel #28
0
class HighlightWindow(PyDialog):
    """
    +-----------+
    | Highlight |
    +--------------------------+
    | Nodes     ______         |
    | Elements  ______         |
    |                          |
    |     Highlight Close      |
    +--------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)
        gui = win_parent

        if gui is None:  # pragma: no cover
            self.highlight_color_float = [0., 0., 0.]
            self.highlight_color_int = [0, 0, 0]
            self._highlight_opacity = 0.9
        else:
            self.highlight_color_float = gui.settings.highlight_color
            self.highlight_color_int = [int(val) for val in self.highlight_color_float]
            #self.highlight_color_int = gui.settings.highlight_color_int
            self._highlight_opacity = gui.settings.highlight_opacity
        self._updated_highlight = False

        self.actors = []
        self._default_font_size = data['font_size']
        self.model_name = data['model_name']
        assert len(self.model_name) > 0, self.model_name

        #self._default_annotation_size = data['annotation_size'] # int
        #self.default_magnify = data['magnify']

        if 'nodes_pound' in data: # testing
            nodes_pound = data['nodes_pound']
            elements_pound = data['elements_pound']
            nodes = np.arange(1, nodes_pound+1)
            elements = np.arange(1, elements_pound+1)
        else:
            # gui
            nodes = gui.get_node_ids(model_name=self.model_name)
            elements = gui.get_element_ids(model_name=self.model_name)
            nodes_pound = nodes.max()
            elements_pound = elements.max()

        self.nodes = nodes
        self.elements = elements
        self._nodes_pound = nodes_pound
        self._elements_pound = elements_pound

        self.setWindowTitle('Highlight')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        #self.show()

    def create_widgets(self):
        """creates the display window"""
        # Text Size

        model_name = self.model_name
        self.nodes_label = QLabel("Nodes:")
        self.nodes_edit = QNodeEdit(self, model_name, pick_style='area', tab_to_next=False)

        self.elements_label = QLabel("Elements:")
        self.elements_edit = QElementEdit(self, model_name, pick_style='area', tab_to_next=False)

        #-----------------------------------------------------------------------
        # Highlight Color
        self.highlight_opacity_label = QLabel("Highlight Opacity:")
        self.highlight_opacity_edit = QDoubleSpinBox(self)
        self.highlight_opacity_edit.setValue(self._highlight_opacity)
        self.highlight_opacity_edit.setRange(0.1, 1.0)
        self.highlight_opacity_edit.setDecimals(1)
        self.highlight_opacity_edit.setSingleStep(0.1)
        self.highlight_opacity_button = QPushButton("Default")

        # Text Color
        self.highlight_color_label = QLabel("Highlight Color:")
        self.highlight_color_edit = QPushButtonColor(self.highlight_color_int)
        #-----------------------------------------------------------------------
        # closing
        self.show_button = QPushButton("Show")
        self.clear_button = QPushButton("Clear")
        self.close_button = QPushButton("Close")

    def create_layout(self):
        """displays the menu objects"""
        grid = QGridLayout()

        irow = 0
        grid.addWidget(self.nodes_label, irow, 0)
        grid.addWidget(self.nodes_edit, irow, 1)
        irow += 1

        grid.addWidget(self.elements_label, irow, 0)
        grid.addWidget(self.elements_edit, irow, 1)
        irow += 1

        grid.addWidget(self.highlight_color_label, irow, 0)
        grid.addWidget(self.highlight_color_edit, irow, 1)
        self.highlight_color_label.setVisible(False)
        self.highlight_color_edit.setVisible(False)
        irow += 1

        grid.addWidget(self.highlight_opacity_label, irow, 0)
        grid.addWidget(self.highlight_opacity_edit, irow, 1)
        self.highlight_opacity_label.setVisible(False)
        self.highlight_opacity_edit.setVisible(False)
        irow += 1

        #self.create_legend_widgets()
        #grid2 = self.create_legend_layout()
        ok_cancel_box = QHBoxLayout()
        ok_cancel_box.addWidget(self.show_button)
        ok_cancel_box.addWidget(self.clear_button)
        ok_cancel_box.addWidget(self.close_button)

        vbox = QVBoxLayout()
        vbox.addLayout(grid)
        #vbox.addStretch()
        #vbox.addLayout(grid2)
        vbox.addStretch()

        vbox.addLayout(ok_cancel_box)
        self.setLayout(vbox)

    def set_connections(self):
        """creates the actions for the menu"""
        self.highlight_color_edit.clicked.connect(self.on_highlight_color)
        self.highlight_opacity_edit.valueChanged.connect(self.on_highlight_opacity)
        self.nodes_edit.textChanged.connect(self.on_validate)
        self.elements_edit.textChanged.connect(self.on_validate)
        self.show_button.clicked.connect(self.on_show)
        self.clear_button.clicked.connect(self.on_remove_actors)
        self.close_button.clicked.connect(self.on_close)
        # closeEvent

    def on_font(self, value=None):
        """update the font for the current window"""
        if value is None:
            value = self.font_size_edit.value()
        font = QtGui.QFont()
        font.setPointSize(value)
        self.setFont(font)

    def on_highlight_color(self):
        """
        Choose a highlight color

        TODO: not implemented
        """
        title = "Choose a highlight color"
        rgb_color_ints = self.highlight_color_int
        color_edit = self.highlight_color_edit
        func_name = 'set_highlight_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.highlight_color_int = rgb_color_ints
            self.highlight_color_float = rgb_color_floats

    def on_highlight_opacity(self, value=None):
        """
        update the highlight opacity

        TODO: not implemented
        """
        if value is None:
            value = self.highlight_opacity_edit.value()
        self._highlight_opacity = value
        if self.win_parent is not None:
            self.win_parent.settings.set_highlight_opacity(value)

    def _background_color(self, title, color_edit, rgb_color_ints, func_name):
        """helper method for ``on_background_color`` and ``on_background_color2``"""
        passed, rgb_color_ints, rgb_color_floats = self.on_color(
            color_edit, rgb_color_ints, title)
        if passed:
            if self.win_parent is not None:
                settings = self.win_parent.settings
                func_background_color = getattr(settings, func_name)
                func_background_color(rgb_color_floats)
        return passed, rgb_color_ints, rgb_color_floats

    def on_color(self, color_edit, rgb_color_ints, title):
        """pops a color dialog"""
        col = QColorDialog.getColor(QtGui.QColor(*rgb_color_ints), self, title)
        if not col.isValid():
            return False, rgb_color_ints, None

        color_float = col.getRgbF()[:3]  # floats
        color_int = [int(colori * 255) for colori in color_float]

        assert isinstance(color_float[0], float), color_float
        assert isinstance(color_int[0], int), color_int

        color_edit.setStyleSheet(
            "QPushButton {"
            "background-color: rgb(%s, %s, %s);" % tuple(color_int) +
            #"border:1px solid rgb(255, 170, 255); "
            "}")
        return True, color_int, color_float

    #---------------------------------------------------------------------------

    def on_validate(self):
        """makes sure that all attributes are valid before doing any actions"""
        unused_nodes, flag1 = check_patran_syntax(self.nodes_edit, pound=self._nodes_pound)
        unused_elements, flag2 = check_patran_syntax(self.elements_edit, pound=self._elements_pound)
        if all([flag1, flag2]):
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_show(self):
        """show the highlight"""
        passed = self.on_validate()
        self.parent().mouse_actions.get_grid_selected(self.model_name)

        if passed and self.win_parent is not None:
            nodes, unused_flag1 = check_patran_syntax(self.nodes_edit, pound=self._nodes_pound)
            elements, unused_flag2 = check_patran_syntax(
                self.elements_edit, pound=self._elements_pound)
            if len(nodes) == 0 and len(elements) == 0:
                return False
            nodes_filtered = np.intersect1d(self.nodes, nodes)
            elements_filtered = np.intersect1d(self.elements, elements)
            nnodes = len(nodes_filtered)
            nelements = len(elements_filtered)
            if nnodes == 0 and nelements == 0:
                return False
            self.on_remove_actors()


            gui = self.parent()
            mouse_actions = gui.mouse_actions
            grid = mouse_actions.get_grid_selected(self.model_name)

            actors = create_highlighted_actors(
                gui, grid,
                all_nodes=self.nodes, nodes=nodes_filtered,
                all_elements=self.elements, elements=elements_filtered)

            if actors:
                add_actors_to_gui(gui, actors, render=True)
                self.actors = actors
        return passed

    def on_remove_actors(self):
        """removes multiple vtk actors"""
        gui = self.parent()
        if gui is not None:
            remove_actors_from_gui(gui, self.actors, render=True)
        self.actors = []

    def on_close(self):
        """close the window"""
        self.on_remove_actors()
        self.out_data['close'] = True
        self.close()