Example #1
0
    def create_widget(self):
        self.check_param(self.param, assert_error=True)

        self.default = self.param['range'][0]
        if 'default' in self.param.keys():
            if self.param['default']:
                self.default = self.param['default']
        self.widget_group = QWidget()
        slider = QSlider(Qt.Horizontal)

        slider.setValue(self.default)
        slider.setRange(self.param['range'][0], self.param['range'][1])

        self.widget = QSpinBox()
        self.widget.setValue(self.default)
        self.widget.setRange(self.param['range'][0], self.param['range'][1])

        self.widget.valueChanged.connect(slider.setValue)
        slider.valueChanged.connect(self.widget.setValue)

        h_box = QHBoxLayout()
        h_box.addWidget(slider)
        h_box.addWidget(self.widget)
        h_box.addStretch(1)
        self.widget_group.setLayout(h_box)
Example #2
0
    def __init__(self, layer):
        super().__init__()

        self.layer = layer
        layer.events.blending.connect(self._on_blending_change)
        layer.events.opacity.connect(self._on_opacity_change)
        self.setObjectName('layer')
        self.setMouseTracking(True)

        self.grid_layout = QGridLayout()
        self.grid_layout.setContentsMargins(0, 0, 0, 0)
        self.grid_layout.setSpacing(2)
        self.setLayout(self.grid_layout)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        sld.setValue(self.layer.opacity * 100)
        sld.valueChanged[int].connect(
            lambda value=sld: self.changeOpacity(value))
        self.opacitySilder = sld

        blend_comboBox = QComboBox()
        for blend in Blending:
            blend_comboBox.addItem(str(blend))
        index = blend_comboBox.findText(self.layer.blending,
                                        Qt.MatchFixedString)
        blend_comboBox.setCurrentIndex(index)
        blend_comboBox.activated[str].connect(
            lambda text=blend_comboBox: self.changeBlending(text))
        self.blendComboBox = blend_comboBox
Example #3
0
    def createBottomRightGroupBox(self):
        self.bottomRightGroupBox = QGroupBox("Group 3")
        self.bottomRightGroupBox.setCheckable(True)
        self.bottomRightGroupBox.setChecked(True)

        lineEdit = QLineEdit('s3cRe7')
        lineEdit.setEchoMode(QLineEdit.Password)

        spinBox = QSpinBox(self.bottomRightGroupBox)
        spinBox.setValue(50)

        dateTimeEdit = QDateTimeEdit(self.bottomRightGroupBox)
        dateTimeEdit.setDateTime(QDateTime.currentDateTime())

        slider = QSlider(Qt.Horizontal, self.bottomRightGroupBox)
        slider.setValue(40)

        scrollBar = QScrollBar(Qt.Horizontal, self.bottomRightGroupBox)
        scrollBar.setValue(60)

        dial = QDial(self.bottomRightGroupBox)
        dial.setValue(30)
        dial.setNotchesVisible(True)

        layout = QGridLayout()
        layout.addWidget(lineEdit, 0, 0, 1, 2)
        layout.addWidget(spinBox, 1, 0, 1, 2)
        layout.addWidget(dateTimeEdit, 2, 0, 1, 2)
        layout.addWidget(slider, 3, 0)
        layout.addWidget(scrollBar, 4, 0)
        layout.addWidget(dial, 3, 1, 2, 1)
        layout.setRowStretch(5, 1)
        self.bottomRightGroupBox.setLayout(layout)
Example #4
0
class IntelligentSlider(QWidget):
    ''' A slider that adds a 'name' attribute and calls a callback
    with 'name' as an argument to the registerd callback.

    This allows you to create large groups of sliders in a loop,
    but still keep track of the individual events

    It also prints a label below the slider.

    The range of the slider is hardcoded from zero - 1000,
    but it supports a conversion factor so you can scale the results'''

    def __init__(self, name, a, b, callback):
        QWidget.__init__(self)
        self.name = name
        self.callback = callback
        self.a = a
        self.b = b
        self.manually_triggered = False

        self.slider = QSlider()
        self.slider.setRange(0, 1000)
        self.slider.setValue(500)
        self.slider.valueChanged.connect(self.slider_changed)

        self.name_label = QLabel()
        self.name_label.setText(self.name)
        self.name_label.setAlignment(QtCore.Qt.AlignCenter)

        self.value_label = QLabel()
        self.value_label.setText('%2.2f' % (self.slider.value() * self.a
                                             + self.b))
        self.value_label.setAlignment(QtCore.Qt.AlignCenter)

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.name_label, 0, 0)
        self.layout.addWidget(self.slider, 1, 0, QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.value_label, 2, 0)

    # bind this to the valueChanged signal of the slider
    def slider_changed(self, val):
        val = self.val()
        self.value_label.setText(str(val)[:4])

        if not self.manually_triggered:
            self.callback(self.name, val)

    def set_conv_fac(self, a, b):
        self.a = a
        self.b = b

    def set_value(self, val):
        self.manually_triggered = True
        self.slider.setValue(int((val - self.b) / self.a))
        self.value_label.setText('%2.2f' % val)
        self.manually_triggered = False

    def val(self):
        return self.slider.value() * self.a + self.b
Example #5
0
class IntelligentSlider(QWidget):
    ''' A slider that adds a 'name' attribute and calls a callback
    with 'name' as an argument to the registerd callback.

    This allows you to create large groups of sliders in a loop,
    but still keep track of the individual events

    It also prints a label below the slider.

    The range of the slider is hardcoded from zero - 1000,
    but it supports a conversion factor so you can scale the results'''
    def __init__(self, name, a, b, callback):
        QWidget.__init__(self)
        self.name = name
        self.callback = callback
        self.a = a
        self.b = b
        self.manually_triggered = False

        self.slider = QSlider()
        self.slider.setRange(0, 1000)
        self.slider.setValue(500)
        self.slider.valueChanged.connect(self.slider_changed)

        self.name_label = QLabel()
        self.name_label.setText(self.name)
        self.name_label.setAlignment(QtCore.Qt.AlignCenter)

        self.value_label = QLabel()
        self.value_label.setText('%2.2f' %
                                 (self.slider.value() * self.a + self.b))
        self.value_label.setAlignment(QtCore.Qt.AlignCenter)

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.name_label, 0, 0)
        self.layout.addWidget(self.slider, 1, 0, QtCore.Qt.AlignHCenter)
        self.layout.addWidget(self.value_label, 2, 0)

    # bind this to the valueChanged signal of the slider
    def slider_changed(self, val):
        val = self.val()
        self.value_label.setText(str(val)[:4])

        if not self.manually_triggered:
            self.callback(self.name, val)

    def set_conv_fac(self, a, b):
        self.a = a
        self.b = b

    def set_value(self, val):
        self.manually_triggered = True
        self.slider.setValue(int((val - self.b) / self.a))
        self.value_label.setText('%2.2f' % val)
        self.manually_triggered = False

    def val(self):
        return self.slider.value() * self.a + self.b
Example #6
0
    def __init__(self, theme='dark', emphasized=False):
        super().__init__(None)
        self.setProperty('emphasized', emphasized)
        self.setStyleSheet(template(raw_stylesheet, **palettes[theme]))
        lay = QVBoxLayout()
        self.setLayout(lay)
        lay.addWidget(QPushButton('push button'))
        box = QComboBox()
        box.addItems(['a', 'b', 'c', 'cd'])
        lay.addWidget(box)
        lay.addWidget(QFontComboBox())

        hbox = QHBoxLayout()
        chk = QCheckBox('tristate')
        chk.setToolTip('I am a tooltip')
        chk.setTristate(True)
        chk.setCheckState(Qt.PartiallyChecked)
        chk3 = QCheckBox('checked')
        chk3.setChecked(True)
        hbox.addWidget(QCheckBox('unchecked'))
        hbox.addWidget(chk)
        hbox.addWidget(chk3)
        lay.addLayout(hbox)

        lay.addWidget(TabDemo(emphasized=emphasized))

        sld = QSlider(Qt.Horizontal)
        sld.setValue(50)
        lay.addWidget(sld)
        scroll = QScrollBar(Qt.Horizontal)
        scroll.setValue(50)
        lay.addWidget(scroll)
        lay.addWidget(QHRangeSlider(parent=self))
        text = QTextEdit()
        text.setMaximumHeight(100)
        text.setHtml(blurb)
        lay.addWidget(text)
        lay.addWidget(QTimeEdit())
        edit = QLineEdit()
        edit.setPlaceholderText('LineEdit placeholder...')
        lay.addWidget(edit)
        lay.addWidget(QLabel('label'))
        prog = QProgressBar()
        prog.setValue(50)
        lay.addWidget(prog)
        groupBox = QGroupBox("Exclusive Radio Buttons")
        radio1 = QRadioButton("&Radio button 1")
        radio2 = QRadioButton("R&adio button 2")
        radio3 = QRadioButton("Ra&dio button 3")
        radio1.setChecked(True)
        hbox = QHBoxLayout()
        hbox.addWidget(radio1)
        hbox.addWidget(radio2)
        hbox.addWidget(radio3)
        hbox.addStretch(1)
        groupBox.setLayout(hbox)
        lay.addWidget(groupBox)
Example #7
0
class QLabeledSlider(QWidget):
    """
    A labeled slider widget
    """

    range = None
    integer = None

    def __init__(self, parent=None):

        super(QLabeledSlider, self).__init__(parent)

        self._range = range

        self._slider = QSlider()
        self._slider.setMinimum(0)
        self._slider.setMaximum(100)
        self._slider.setOrientation(Qt.Horizontal)

        self._label = QLabel('')
        self._layout = QHBoxLayout()
        self._layout.setContentsMargins(2, 2, 2, 2)
        self._layout.addWidget(self._slider)
        self._layout.addWidget(self._label)

        self._slider.valueChanged.connect(self._update_label)

        self.setLayout(self._layout)

    def _update_label(self, *args):
        self._label.setText(str(self.value()))

    @property
    def valueChanged(self):
        return self._slider.valueChanged

    def value(self, layer=None, view=None):
        value = self._slider.value() / 100. * (self.range[1] -
                                               self.range[0]) + self.range[0]
        if self.integer:
            return int(value)
        else:
            return (value)

    _in_set_value = False

    def setValue(self, value):
        if self._in_set_value:
            return
        self._in_set_value = True
        value = int(100 * (value - self.range[0]) /
                    (self.range[1] - self.range[0]))
        self._slider.setValue(value)
        self._in_set_value = False
Example #8
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)
        self.layer.events.face_color.connect(self._on_face_color_change)

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setFixedWidth(75)
        sld.setMinimum(0)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        value = self.layer.edge_width
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value.mean()
        sld.setValue(int(value))
        sld.valueChanged[int].connect(lambda value=sld:
                                      self.changeWidth(value))
        self.widthSlider = sld
        self.grid_layout.addWidget(QLabel('width:'), 3, 0)
        self.grid_layout.addWidget(sld, 3, 1)

        face_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            face_comboBox.addItem(c)
        index = face_comboBox.findText(
            self.layer.face_color, Qt.MatchFixedString)
        if index >= 0:
            face_comboBox.setCurrentIndex(index)
        face_comboBox.activated[str].connect(lambda text=face_comboBox:
                                             self.changeFaceColor(text))
        self.faceComboBox = face_comboBox
        self.grid_layout.addWidget(QLabel('face_color:'), 4, 0)
        self.grid_layout.addWidget(face_comboBox, 4, 1)

        edge_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            edge_comboBox.addItem(c)
        index = edge_comboBox.findText(
            self.layer.edge_color, Qt.MatchFixedString)
        if index >= 0:
            edge_comboBox.setCurrentIndex(index)
        edge_comboBox.activated[str].connect(lambda text=edge_comboBox:
                                             self.changeEdgeColor(text))
        self.edgeComboBox = edge_comboBox
        self.grid_layout.addWidget(QLabel('edge_color:'), 5, 0)
        self.grid_layout.addWidget(edge_comboBox, 5, 1)

        self.setExpanded(False)
Example #9
0
class QLabeledSlider(QWidget):
    """
    A labeled slider widget
    """

    range = None
    integer = None

    def __init__(self, parent=None):

        super(QLabeledSlider, self).__init__(parent)

        self._range = range

        self._slider = QSlider()
        self._slider.setMinimum(0)
        self._slider.setMaximum(100)
        self._slider.setOrientation(Qt.Horizontal)

        self._label = QLabel('')
        self._layout = QHBoxLayout()
        self._layout.setContentsMargins(2, 2, 2, 2)
        self._layout.addWidget(self._slider)
        self._layout.addWidget(self._label)

        self._slider.valueChanged.connect(self._update_label)

        self.setLayout(self._layout)

    def _update_label(self, *args):
        self._label.setText(str(self.value()))

    @property
    def valueChanged(self):
        return self._slider.valueChanged

    def value(self, layer=None, view=None):
        value = self._slider.value() / 100. * (self.range[1] - self.range[0]) + self.range[0]
        if self.integer:
            return int(value)
        else:
            return(value)

    _in_set_value = False

    def setValue(self, value):
        if self._in_set_value:
            return
        self._in_set_value = True
        value = int(100 * (value - self.range[0]) / (self.range[1] - self.range[0]))
        self._slider.setValue(value)
        self._in_set_value = False
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.gamma.connect(self._on_gamma_change)
        self.layer.events.contrast_limits.connect(
            self._on_contrast_limits_change
        )

        comboBox = QtColormapComboBox(self)
        comboBox.setObjectName("colormapComboBox")
        comboBox._allitems = set(self.layer.colormaps)

        for name, cm in AVAILABLE_COLORMAPS.items():
            if name in self.layer.colormaps:
                comboBox.addItem(cm._display_name, name)

        comboBox.activated[str].connect(self.changeColor)
        self.colormapComboBox = comboBox

        # Create contrast_limits slider
        self.contrastLimitsSlider = QHRangeSlider(
            self.layer.contrast_limits,
            self.layer.contrast_limits_range,
            parent=self,
        )
        self.contrastLimitsSlider.mousePressEvent = self._clim_mousepress
        set_clim = partial(setattr, self.layer, 'contrast_limits')
        set_climrange = partial(setattr, self.layer, 'contrast_limits_range')
        self.contrastLimitsSlider.valuesChanged.connect(set_clim)
        self.contrastLimitsSlider.rangeChanged.connect(set_climrange)

        # gamma slider
        sld = QSlider(Qt.Horizontal, parent=self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(2)
        sld.setMaximum(200)
        sld.setSingleStep(2)
        sld.setValue(100)
        sld.valueChanged.connect(self.gamma_slider_changed)
        self.gammaSlider = sld
        self._on_gamma_change()

        self.colorbarLabel = QLabel(parent=self)
        self.colorbarLabel.setObjectName('colorbar')
        self.colorbarLabel.setToolTip(trans._('Colorbar'))

        self._on_colormap_change()
Example #11
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.contrast_limits.connect(
            lambda e: self.contrast_limits_slider_update()
        )
        self.layer.events.gamma.connect(lambda e: self.gamma_slider_update())

        comboBox = QComboBox()
        for cmap in self.layer.colormaps:
            comboBox.addItem(cmap)
        comboBox._allitems = set(self.layer.colormaps)
        comboBox.activated[str].connect(
            lambda text=comboBox: self.changeColor(text)
        )
        self.colormapComboBox = comboBox

        # Create contrast_limits slider
        self.contrastLimitsSlider = QHRangeSlider(
            slider_range=[0, 1, 0.0001], values=[0, 1]
        )
        self.contrastLimitsSlider.setEmitWhileMoving(True)
        self.contrastLimitsSlider.collapsable = False
        self.contrastLimitsSlider.setEnabled(True)

        self.contrastLimitsSlider.rangeChanged.connect(
            self.contrast_limits_slider_changed
        )
        self.contrast_limits_slider_update()

        # gamma slider
        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(2)
        sld.setMaximum(200)
        sld.setSingleStep(2)
        sld.setValue(100)
        sld.valueChanged[int].connect(self.gamma_slider_changed)
        self.gammaSlider = sld
        self.gamma_slider_update()

        self.colorbarLabel = QLabel()
        self.colorbarLabel.setObjectName('colorbar')
        self.colorbarLabel.setToolTip('Colorbar')

        self._on_colormap_change(None)
Example #12
0
class SliderWidget(HLayoutMixin, LineEditWidget):
    """
    IntItem with Slider
    """

    DATA_TYPE = int

    def __init__(self, item, parent_layout):
        super(SliderWidget, self).__init__(item, parent_layout)
        self.slider = self.vmin = self.vmax = None
        if item.get_prop_value("display", "slider"):
            self.vmin = item.get_prop_value("data", "min")
            self.vmax = item.get_prop_value("data", "max")
            assert (
                self.vmin is not None and self.vmax is not None
            ), "SliderWidget requires that item min/max have been defined"
            self.slider = QSlider()
            self.slider.setOrientation(Qt.Horizontal)
            self.setup_slider(item)
            self.slider.valueChanged.connect(self.value_changed)
            self.group.addWidget(self.slider)

    def value_to_slider(self, value):
        return value

    def slider_to_value(self, value):
        return value

    def setup_slider(self, item):
        self.slider.setRange(self.vmin, self.vmax)

    def update(self, value):
        """Reimplement LineEditWidget method"""
        LineEditWidget.update(self, value)
        if self.slider is not None and isinstance(value, self.DATA_TYPE):
            self.slider.blockSignals(True)
            self.slider.setValue(self.value_to_slider(value))
            self.slider.blockSignals(False)

    def value_changed(self, ivalue):
        """Update the lineedit"""
        value = str(self.slider_to_value(ivalue))
        self.edit.setText(value)
        self.update(value)
Example #13
0
    def open_perspective_popup(self):
        """Show a slider to control the viewer `camera.perspective`."""
        if self.viewer.dims.ndisplay != 3:
            return

        # make slider connected to perspective parameter
        sld = QSlider(Qt.Horizontal, self)
        sld.setRange(0, max(90, self.viewer.camera.perspective))
        sld.setValue(self.viewer.camera.perspective)
        sld.valueChanged.connect(
            lambda v: setattr(self.viewer.camera, 'perspective', v))

        # make layout
        layout = QHBoxLayout()
        layout.addWidget(QLabel(trans._('Perspective'), self))
        layout.addWidget(sld)

        # popup and show
        pop = QtPopup(self)
        pop.frame.setLayout(layout)
        pop.show_above_mouse()
Example #14
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.gamma.connect(self.gamma_slider_update)
        self.layer.events.contrast_limits.connect(self._on_clims_change)

        comboBox = QComboBox()
        comboBox.addItems(self.layer.colormaps)
        comboBox._allitems = set(self.layer.colormaps)
        comboBox.activated[str].connect(self.changeColor)
        self.colormapComboBox = comboBox

        # Create contrast_limits slider
        self.contrastLimitsSlider = QHRangeSlider(
            self.layer.contrast_limits, self.layer.contrast_limits_range
        )
        self.contrastLimitsSlider.mousePressEvent = self._clim_mousepress
        set_clim = partial(setattr, self.layer, 'contrast_limits')
        set_climrange = partial(setattr, self.layer, 'contrast_limits_range')
        self.contrastLimitsSlider.valuesChanged.connect(set_clim)
        self.contrastLimitsSlider.rangeChanged.connect(set_climrange)

        # gamma slider
        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(2)
        sld.setMaximum(200)
        sld.setSingleStep(2)
        sld.setValue(100)
        sld.valueChanged.connect(self.gamma_slider_changed)
        self.gammaSlider = sld
        self.gamma_slider_update()

        self.colorbarLabel = QLabel()
        self.colorbarLabel.setObjectName('colorbar')
        self.colorbarLabel.setToolTip('Colorbar')

        self._on_colormap_change()
    def __init__(self, parent):
        super(MainWidget, self).__init__(parent)

        self._layout = QHBoxLayout(self)
        self.setLayout(self._layout)

        roundbar = QRoundProgressBar(self)
        roundbar.setBarStyle(QRoundProgressBar.BarStyle.PIE)
        roundbar.setFixedWidth(300)
        roundbar.setFixedHeight(300)
        roundbar.setDecimals(1)
        self._layout.addWidget(roundbar)

        self._controlWidget = QWidget(self)
        self._controlWidget.setMaximumHeight(200)
        self._controlWidgetLayout = QFormLayout(self._controlWidget)
        self._controlWidget.setLayout(self._controlWidgetLayout)

        bar_style_label = QLabel("Bar style", self._controlWidget)
        style = QPushButton(self._controlWidget)
        style.setText("Change bar style")
        self._controlWidgetLayout.addRow(bar_style_label, style)

        app_style_label = QLabel("App style", self._controlWidget)
        picker = StylePickerHorizontal(self._controlWidget)
        self._controlWidgetLayout.addRow(app_style_label, picker)

        style.clicked.connect(lambda: roundbar.setBarStyle(get_style()))

        slider_label = QLabel("Progress", self._controlWidget)
        slider = QSlider(Qt.Horizontal, self._controlWidget)
        slider.setRange(0, 100)
        slider.valueChanged.connect(roundbar.setValue)
        slider.setValue(28)
        self._controlWidgetLayout.addRow(slider_label, slider)
        self._layout.addWidget(self._controlWidget)
Example #16
0
class AnimateDialog(QDialog):
    def __init__(self, vpoints: Sequence[VPoint], vlinks: Sequence[VLink],
                 path: _Paths, slider_path: _SliderPaths, monochrome: bool,
                 parent: QWidget):
        super(AnimateDialog, self).__init__(parent)
        self.setWindowTitle("Vector Animation")
        self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint
                            & ~Qt.WindowContextHelpButtonHint)
        self.setMinimumSize(800, 600)
        self.setModal(True)
        main_layout = QVBoxLayout(self)
        self.canvas = _DynamicCanvas(vpoints, vlinks, path, slider_path, self)
        self.canvas.set_monochrome_mode(monochrome)
        self.canvas.update_pos.connect(self.__set_pos)
        layout = QHBoxLayout(self)
        pt_option = QComboBox(self)
        pt_option.addItems([f"P{p}" for p in range(len(vpoints))])
        layout.addWidget(pt_option)
        value_label = QLabel(self)

        @Slot(int)
        def show_values(ind: int):
            vel, vel_deg = self.canvas.get_vel(ind)
            acc, acc_deg = self.canvas.get_acc(ind)
            value_label.setText(
                f"Velocity: {vel:.04f} ({vel_deg:.04f}deg) | "
                f"Acceleration: {acc:.04f} ({acc_deg:.04f}deg)")

        pt_option.currentIndexChanged.connect(show_values)
        layout.addWidget(value_label)
        self.pos_label = QLabel(self)
        layout.addItem(
            QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
        layout.addWidget(self.pos_label)
        main_layout.addLayout(layout)
        main_layout.addWidget(self.canvas)
        layout = QHBoxLayout(self)
        self.play = QPushButton(QIcon(QPixmap(":/icons/play.png")), "", self)
        self.play.setCheckable(True)
        self.play.clicked.connect(self.__play)
        layout.addWidget(self.play)
        self.slider = QSlider(Qt.Horizontal, self)
        self.slider.setMaximum(max(len(p) for p in path) - 1)
        self.slider.valueChanged.connect(self.canvas.set_index)
        layout.addWidget(self.slider)
        layout.addWidget(QLabel("Total times:", self))
        factor = QDoubleSpinBox(self)
        factor.valueChanged.connect(self.canvas.set_factor)
        factor.setSuffix('s')
        factor.setRange(0.01, 999999)
        factor.setValue(10)
        layout.addWidget(factor)
        main_layout.addLayout(layout)
        self.timer = QTimer()
        self.timer.setInterval(10)
        self.timer.timeout.connect(self.__move_ind)

    @Slot()
    def __move_ind(self):
        """Move indicator."""
        value = self.slider.value() + 1
        self.slider.setValue(value)
        if value > self.slider.maximum():
            self.slider.setValue(0)

    @Slot(float, float)
    def __set_pos(self, x: float, y: float) -> None:
        """Set mouse position."""
        self.pos_label.setText(f"({x:.04f}, {y:.04f})")

    @Slot()
    def __play(self):
        """Start playing."""
        if self.play.isChecked():
            self.timer.start()
        else:
            self.timer.stop()
Example #17
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self.set_mode)
        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)
        self.layer.events.face_color.connect(self._on_face_color_change)
        self.layer.events.editable.connect(self._on_editable_change)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        value = self.layer.edge_width
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value.mean()
        sld.setValue(int(value))
        sld.valueChanged[int].connect(
            lambda value=sld: self.changeWidth(value)
        )
        self.widthSlider = sld

        face_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            face_comboBox.addItem(c)
        face_comboBox.activated[str].connect(
            lambda text=face_comboBox: self.changeFaceColor(text)
        )
        self.faceComboBox = face_comboBox
        self.faceColorSwatch = QFrame()
        self.faceColorSwatch.setObjectName('swatch')
        self.faceColorSwatch.setToolTip('Face color swatch')
        self._on_face_color_change(None)

        edge_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            edge_comboBox.addItem(c)
        edge_comboBox.activated[str].connect(
            lambda text=edge_comboBox: self.changeEdgeColor(text)
        )
        self.edgeComboBox = edge_comboBox
        self.edgeColorSwatch = QFrame()
        self.edgeColorSwatch.setObjectName('swatch')
        self.edgeColorSwatch.setToolTip('Edge color swatch')
        self._on_edge_color_change(None)

        self.select_button = QtModeButton(
            layer, 'select', Mode.SELECT, 'Select shapes'
        )
        self.direct_button = QtModeButton(
            layer, 'direct', Mode.DIRECT, 'Select vertices'
        )
        self.panzoom_button = QtModeButton(
            layer, 'zoom', Mode.PAN_ZOOM, 'Pan/zoom'
        )
        self.rectangle_button = QtModeButton(
            layer, 'rectangle', Mode.ADD_RECTANGLE, 'Add rectangles'
        )
        self.ellipse_button = QtModeButton(
            layer, 'ellipse', Mode.ADD_ELLIPSE, 'Add ellipses'
        )
        self.line_button = QtModeButton(
            layer, 'line', Mode.ADD_LINE, 'Add lines'
        )
        self.path_button = QtModeButton(
            layer, 'path', Mode.ADD_PATH, 'Add paths'
        )
        self.polygon_button = QtModeButton(
            layer, 'polygon', Mode.ADD_POLYGON, 'Add polygons'
        )
        self.vertex_insert_button = QtModeButton(
            layer, 'vertex_insert', Mode.VERTEX_INSERT, 'Insert vertex'
        )
        self.vertex_remove_button = QtModeButton(
            layer, 'vertex_remove', Mode.VERTEX_REMOVE, 'Remove vertex'
        )

        self.move_front_button = QtMoveFrontButton(layer)
        self.move_back_button = QtMoveBackButton(layer)
        self.delete_button = QtDeleteShapeButton(layer)
        self.panzoom_button.setChecked(True)

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.select_button)
        self.button_group.addButton(self.direct_button)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.rectangle_button)
        self.button_group.addButton(self.ellipse_button)
        self.button_group.addButton(self.line_button)
        self.button_group.addButton(self.path_button)
        self.button_group.addButton(self.polygon_button)
        self.button_group.addButton(self.vertex_insert_button)
        self.button_group.addButton(self.vertex_remove_button)

        button_grid = QGridLayout()
        button_grid.addWidget(self.vertex_remove_button, 0, 1)
        button_grid.addWidget(self.vertex_insert_button, 0, 2)
        button_grid.addWidget(self.delete_button, 0, 3)
        button_grid.addWidget(self.direct_button, 0, 4)
        button_grid.addWidget(self.select_button, 0, 5)
        button_grid.addWidget(self.panzoom_button, 0, 6)
        button_grid.addWidget(self.move_back_button, 1, 0)
        button_grid.addWidget(self.move_front_button, 1, 1)
        button_grid.addWidget(self.ellipse_button, 1, 2)
        button_grid.addWidget(self.rectangle_button, 1, 3)
        button_grid.addWidget(self.polygon_button, 1, 4)
        button_grid.addWidget(self.line_button, 1, 5)
        button_grid.addWidget(self.path_button, 1, 6)
        button_grid.setColumnStretch(2, 2)
        button_grid.setSpacing(4)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_grid, 0, 0, 1, 3)
        self.grid_layout.addWidget(QLabel('opacity:'), 1, 0)
        self.grid_layout.addWidget(self.opacitySilder, 1, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('edge width:'), 2, 0)
        self.grid_layout.addWidget(self.widthSlider, 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('face color:'), 4, 0)
        self.grid_layout.addWidget(self.faceComboBox, 4, 2)
        self.grid_layout.addWidget(self.faceColorSwatch, 4, 1)
        self.grid_layout.addWidget(QLabel('edge color:'), 5, 0)
        self.grid_layout.addWidget(self.edgeComboBox, 5, 2)
        self.grid_layout.addWidget(self.edgeColorSwatch, 5, 1)
        self.grid_layout.setRowStretch(6, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)
Example #18
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.selected_label.connect(self._on_selection_change)
        self.layer.events.brush_size.connect(self._on_brush_size_change)
        self.layer.events.contiguous.connect(self._on_contig_change)
        self.layer.events.n_dimensional.connect(self._on_n_dim_change)

        self.colormap_update = QPushButton('click')
        self.colormap_update.setObjectName('shuffle')
        self.colormap_update.clicked.connect(self.changeColor)
        self.colormap_update.setFixedWidth(112)
        self.colormap_update.setFixedHeight(25)
        shuffle_label = QLabel('shuffle colors:')
        shuffle_label.setObjectName('shuffle-label')
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(shuffle_label, row, self.name_column)
        self.grid_layout.addWidget(
            self.colormap_update, row, self.property_column
        )

        # selection spinbox
        self.selection_spinbox = QSpinBox()
        self.selection_spinbox.setSingleStep(1)
        self.selection_spinbox.setMinimum(0)
        self.selection_spinbox.setMaximum(2147483647)
        self.selection_spinbox.setValue(self.layer.selected_label)
        self.selection_spinbox.setFixedWidth(75)
        self.selection_spinbox.valueChanged.connect(self.changeSelection)
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(QLabel('label:'), row, self.name_column)
        self.grid_layout.addWidget(
            self.selection_spinbox, row, self.property_column
        )

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setFixedWidth(110)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        value = self.layer.brush_size
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value[:2].mean()
        sld.setValue(int(value))
        sld.valueChanged[int].connect(lambda value=sld: self.changeSize(value))
        self.brush_size_slider = sld
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(
            QLabel('brush size:'), row, self.name_column
        )
        self.grid_layout.addWidget(sld, row, self.property_column)

        contig_cb = QCheckBox()
        contig_cb.setToolTip('contiguous editing')
        contig_cb.setChecked(self.layer.contiguous)
        contig_cb.stateChanged.connect(
            lambda state=contig_cb: self.change_contig(state)
        )
        self.contig_checkbox = contig_cb
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(
            QLabel('contiguous:'), row, self.name_column
        )
        self.grid_layout.addWidget(contig_cb, row, self.property_column)

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip('n-dimensional editing')
        ndim_cb.setChecked(self.layer.n_dimensional)
        ndim_cb.stateChanged.connect(
            lambda state=ndim_cb: self.change_ndim(state)
        )
        self.ndim_checkbox = ndim_cb
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(QLabel('n-dim:'), row, self.name_column)
        self.grid_layout.addWidget(ndim_cb, row, self.property_column)

        self.setExpanded(False)
Example #19
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.current_edge_color.connect(
            self._on_current_edge_color_change)
        self.layer.events.current_face_color.connect(
            self._on_current_face_color_change)
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.text.events.visible.connect(self._on_text_visibility_change)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        value = self.layer.current_edge_width
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value.mean()
        sld.setValue(int(value))
        sld.valueChanged.connect(self.changeWidth)
        self.widthSlider = sld

        self.select_button = QtModeRadioButton(layer,
                                               'select',
                                               Mode.SELECT,
                                               tooltip='Select shapes')
        self.direct_button = QtModeRadioButton(layer,
                                               'direct',
                                               Mode.DIRECT,
                                               tooltip='Select vertices')
        self.panzoom_button = QtModeRadioButton(layer,
                                                'zoom',
                                                Mode.PAN_ZOOM,
                                                tooltip='Pan/zoom',
                                                checked=True)
        self.rectangle_button = QtModeRadioButton(layer,
                                                  'rectangle',
                                                  Mode.ADD_RECTANGLE,
                                                  tooltip='Add rectangles')
        self.ellipse_button = QtModeRadioButton(layer,
                                                'ellipse',
                                                Mode.ADD_ELLIPSE,
                                                tooltip='Add ellipses')
        self.line_button = QtModeRadioButton(layer,
                                             'line',
                                             Mode.ADD_LINE,
                                             tooltip='Add lines')
        self.path_button = QtModeRadioButton(layer,
                                             'path',
                                             Mode.ADD_PATH,
                                             tooltip='Add paths')
        self.polygon_button = QtModeRadioButton(layer,
                                                'polygon',
                                                Mode.ADD_POLYGON,
                                                tooltip='Add polygons')
        self.vertex_insert_button = QtModeRadioButton(layer,
                                                      'vertex_insert',
                                                      Mode.VERTEX_INSERT,
                                                      tooltip='Insert vertex')
        self.vertex_remove_button = QtModeRadioButton(layer,
                                                      'vertex_remove',
                                                      Mode.VERTEX_REMOVE,
                                                      tooltip='Remove vertex')

        self.move_front_button = QtModePushButton(
            layer,
            'move_front',
            slot=self.layer.move_to_front,
            tooltip='Move to front',
        )
        self.move_back_button = QtModePushButton(
            layer,
            'move_back',
            slot=self.layer.move_to_back,
            tooltip='Move to back',
        )
        self.delete_button = QtModePushButton(
            layer,
            'delete_shape',
            slot=self.layer.remove_selected,
            tooltip='Delete selected shapes',
        )

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.select_button)
        self.button_group.addButton(self.direct_button)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.rectangle_button)
        self.button_group.addButton(self.ellipse_button)
        self.button_group.addButton(self.line_button)
        self.button_group.addButton(self.path_button)
        self.button_group.addButton(self.polygon_button)
        self.button_group.addButton(self.vertex_insert_button)
        self.button_group.addButton(self.vertex_remove_button)

        button_grid = QGridLayout()
        button_grid.addWidget(self.vertex_remove_button, 0, 2)
        button_grid.addWidget(self.vertex_insert_button, 0, 3)
        button_grid.addWidget(self.delete_button, 0, 4)
        button_grid.addWidget(self.direct_button, 0, 5)
        button_grid.addWidget(self.select_button, 0, 6)
        button_grid.addWidget(self.panzoom_button, 0, 7)
        button_grid.addWidget(self.move_back_button, 1, 1)
        button_grid.addWidget(self.move_front_button, 1, 2)
        button_grid.addWidget(self.ellipse_button, 1, 3)
        button_grid.addWidget(self.rectangle_button, 1, 4)
        button_grid.addWidget(self.polygon_button, 1, 5)
        button_grid.addWidget(self.line_button, 1, 6)
        button_grid.addWidget(self.path_button, 1, 7)
        button_grid.setContentsMargins(5, 0, 0, 5)
        button_grid.setColumnStretch(0, 1)
        button_grid.setSpacing(4)

        self.faceColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_face_color,
            tooltip='click to set current face color',
        )
        self._on_current_face_color_change()
        self.edgeColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_edge_color,
            tooltip='click to set current edge color',
        )
        self._on_current_edge_color_change()
        self.faceColorEdit.color_changed.connect(self.changeFaceColor)
        self.edgeColorEdit.color_changed.connect(self.changeEdgeColor)

        text_disp_cb = QCheckBox()
        text_disp_cb.setToolTip('toggle text visibility')
        text_disp_cb.setChecked(self.layer.text.visible)
        text_disp_cb.stateChanged.connect(self.change_text_visibility)
        self.textDispCheckBox = text_disp_cb

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_grid, 0, 0, 1, 2)
        self.grid_layout.addWidget(QLabel('opacity:'), 1, 0)
        self.grid_layout.addWidget(self.opacitySlider, 1, 1)
        self.grid_layout.addWidget(QLabel('edge width:'), 2, 0)
        self.grid_layout.addWidget(self.widthSlider, 2, 1)
        self.grid_layout.addWidget(QLabel('blending:'), 3, 0)
        self.grid_layout.addWidget(self.blendComboBox, 3, 1)
        self.grid_layout.addWidget(QLabel('face color:'), 4, 0)
        self.grid_layout.addWidget(self.faceColorEdit, 4, 1)
        self.grid_layout.addWidget(QLabel('edge color:'), 5, 0)
        self.grid_layout.addWidget(self.edgeColorEdit, 5, 1)
        self.grid_layout.addWidget(QLabel('display text:'), 6, 0)
        self.grid_layout.addWidget(self.textDispCheckBox, 6, 1)
        self.grid_layout.setRowStretch(7, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)
Example #20
0
def create_wwwc_tab(apply_adjust):
    Conf = namedtuple("Conf", "min max step default")
    ww_conf = Conf(0, 2000, 1, 350)
    wc_conf = Conf(-2000, 2000, 1, 50)

    tab = QWidget()
    tab.layout = QFormLayout()

    # BUG: 只有一个负号的时候会变成0,应该保留负号
    ww_edit = QLineEdit()
    ww_edit.setValidator(QtGui.QIntValidator(ww_conf.min, ww_conf.max))
    ww_edit.setFixedWidth(50)
    wc_edit = QLineEdit()
    wc_edit.setValidator(QtGui.QIntValidator(wc_conf.min, wc_conf.max))
    wc_edit.setFixedWidth(50)

    ww_slider = QSlider(Qt.Horizontal)  # 窗宽滑动条
    ww_slider.setMinimum(ww_conf.min)
    ww_slider.setMaximum(ww_conf.max)
    ww_slider.setSingleStep(ww_conf.step)
    ww_slider.setValue(ww_conf.default)

    wc_slider = QSlider(Qt.Horizontal)  # 窗位滑动条
    wc_slider.setMinimum(wc_conf.min)
    wc_slider.setMaximum(wc_conf.max)
    wc_slider.setSingleStep(wc_conf.step)
    wc_slider.setValue(wc_conf.default)

    ww_label = QLabel()
    ww_label.setText("窗宽:  ")
    wc_label = QLabel()
    wc_label.setText("窗位:  ")

    ww_combo = QHBoxLayout()
    ww_combo.addWidget(ww_edit)
    ww_combo.addWidget(ww_slider)
    wc_combo = QHBoxLayout()
    wc_combo.addWidget(wc_edit)
    wc_combo.addWidget(wc_slider)

    tab.layout.addRow(ww_label, ww_combo)
    tab.layout.addRow(wc_label, wc_combo)

    tab.setLayout(tab.layout)

    def slider_change(slider, editor):
        def func():
            editor.setText(str(slider.value()))
            apply_adjust(
                functools.partial(wwwc, ww_slider.value(), wc_slider.value()))

        return func

    def edit_changed(editor, slider):
        def func():
            value = editor.text()
            if value == "" or value == "-":
                value = 0
            value = int(value)
            slider.setValue(value)

        return func

    ww_slider.valueChanged.connect(slider_change(ww_slider, ww_edit))
    wc_slider.valueChanged.connect(slider_change(wc_slider, wc_edit))
    ww_edit.textChanged.connect(edit_changed(ww_edit, ww_slider))
    # wc_edit.textChanged.connect(wc_edit_change)

    return tab, "WW/WC"
Example #21
0
class PyDMSlider(QFrame, TextFormatter, PyDMWritableWidget):
    """
    A QSlider with support for Channels and more from PyDM.

    Parameters
    ----------
    parent : QWidget
        The parent widget for the Label
    init_channel : str, optional
        The channel to be used by the widget.
    """
    actionTriggered = Signal(int)
    rangeChanged = Signal(float, float)
    sliderMoved = Signal(float)
    sliderPressed = Signal()
    sliderReleased = Signal()
    valueChanged = Signal(float)

    def __init__(self, parent=None, init_channel=None):
        QFrame.__init__(self, parent)
        PyDMWritableWidget.__init__(self, init_channel=init_channel)
        self.alarmSensitiveContent = True
        self.alarmSensitiveBorder = False
        # Internal values for properties
        self._show_limit_labels = True
        self._show_value_label = True
        self._user_defined_limits = False
        self._needs_limit_info = True
        self._minimum = None
        self._maximum = None
        self._user_minimum = -10.0
        self._user_maximum = 10.0
        self._num_steps = 101
        self._orientation = Qt.Horizontal
        # Set up all the internal widgets that make up a PyDMSlider.
        # We'll add all these things to layouts when we call setup_widgets_for_orientation
        label_size_policy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        self.low_lim_label = QLabel(self)
        self.low_lim_label.setObjectName("lowLimLabel")
        self.low_lim_label.setSizePolicy(label_size_policy)
        self.low_lim_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing | Qt.AlignVCenter)
        self.value_label = QLabel(self)
        self.value_label.setObjectName("valueLabel")
        self.value_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.high_lim_label = QLabel(self)
        self.high_lim_label.setObjectName("highLimLabel")
        self.high_lim_label.setSizePolicy(label_size_policy)
        self.high_lim_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter)
        self._slider = QSlider(parent=self)
        self._slider.setOrientation(Qt.Horizontal)
        self._slider.sliderMoved.connect(self.internal_slider_moved)
        self._slider.sliderPressed.connect(self.internal_slider_pressed)
        self._slider.sliderReleased.connect(self.internal_slider_released)
        self._slider.valueChanged.connect(self.internal_slider_value_changed)
        # self.vertical_layout.addWidget(self._slider)
        # Other internal variables and final setup steps
        self._slider_position_to_value_map = None
        self._mute_internal_slider_changes = False
        self.setup_widgets_for_orientation(self._orientation)
        self.reset_slider_limits()

    def init_for_designer(self):
        """
        Method called after the constructor to tweak configurations for
        when using the widget with the Qt Designer
        """
        self.value = 0.0

    @Property(Qt.Orientation)
    def orientation(self):
        """
        The slider orientation (Horizontal or Vertical)

        Returns
        -------
        int
            Qt.Horizontal or Qt.Vertical
        """
        return self._orientation

    @orientation.setter
    def orientation(self, new_orientation):
        """
        The slider orientation (Horizontal or Vertical)

        Parameters
        ----------
        new_orientation : int
            Qt.Horizontal or Qt.Vertical
        """
        self._orientation = new_orientation
        self.setup_widgets_for_orientation(new_orientation)

    def setup_widgets_for_orientation(self, new_orientation):
        """
        Reconstruct the widget given the orientation.

        Parameters
        ----------
        new_orientation : int
            Qt.Horizontal or Qt.Vertical
        """
        if new_orientation not in (Qt.Horizontal, Qt.Vertical):
            logger.error("Invalid orientation '{0}'. The existing layout will not change.".format(new_orientation))
            return

        layout = None
        if new_orientation == Qt.Horizontal:
            layout = QVBoxLayout()
            layout.setContentsMargins(4, 0, 4, 4)
            label_layout = QHBoxLayout()
            label_layout.addWidget(self.low_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.high_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)
        elif new_orientation == Qt.Vertical:
            layout = QHBoxLayout()
            layout.setContentsMargins(0, 4, 4, 4)
            label_layout = QVBoxLayout()
            label_layout.addWidget(self.high_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.low_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)

        if self.layout() is not None:
            # Trick to remove the existing layout by re-parenting it in an empty widget.
            QWidget().setLayout(self.layout())
        self.setLayout(layout)

    def update_labels(self):
        """
        Update the limits and value labels with the correct values.
        """
        def set_label(value, label_widget):
            if value is None:
                label_widget.setText("")
            else:
                label_widget.setText(self.format_string.format(value))

        set_label(self.minimum, self.low_lim_label)
        set_label(self.maximum, self.high_lim_label)
        set_label(self.value, self.value_label)

    def reset_slider_limits(self):
        """
        Reset the limits and adjust the labels properly for the slider.
        """
        if self.minimum is None or self.maximum is None:
            self._needs_limit_info = True
            self.set_enable_state()
            return
        self._needs_limit_info = False
        self._slider.setMinimum(0)
        self._slider.setMaximum(self._num_steps - 1)
        self._slider.setSingleStep(1)
        self._slider.setPageStep(10)
        self._slider_position_to_value_map = np.linspace(self.minimum, self.maximum, num=self._num_steps)
        self.update_labels()
        self.set_slider_to_closest_value(self.value)
        self.rangeChanged.emit(self.minimum, self.maximum)
        self.set_enable_state()

    def find_closest_slider_position_to_value(self, val):
        """
        Find and returns the index for the closest position on the slider
        for a given value.

        Parameters
        ----------
        val : float

        Returns
        -------
        int
        """
        diff = abs(self._slider_position_to_value_map - float(val))
        return np.argmin(diff)

    def set_slider_to_closest_value(self, val):
        """
        Set the value for the slider according to a given value.

        Parameters
        ----------
        val : float
        """
        if val is None or self._needs_limit_info:
            return
        # When we set the slider to the closest value, it may end up at a slightly
        # different position than val (if val is not in self._slider_position_to_value_map)
        # We don't want that slight difference to get broacast out and put the channel
        # somewhere new.    For example, if the slider can only be at 0.4 or 0.5, but a
        # new value comes in of 0.45, its more important to keep the 0.45 than to change
        # it to where the slider gets set.  Therefore, we mute the internal slider changes
        # so that its valueChanged signal doesn't cause us to emit a signal to PyDM to change
        # the value of the channel.
        self._mute_internal_slider_changes = True
        self._slider.setValue(self.find_closest_slider_position_to_value(val))
        self._mute_internal_slider_changes = False

    def value_changed(self, new_val):
        """
        Callback invoked when the Channel value is changed.

        Parameters
        ----------
        new_val : int or float
            The new value from the channel.
        """
        PyDMWritableWidget.value_changed(self, new_val)
        if hasattr(self, "value_label"):
            self.value_label.setText(self.format_string.format(self.value))
        if not self._slider.isSliderDown():
            self.set_slider_to_closest_value(self.value)

    def ctrl_limit_changed(self, which, new_limit):
        """
        Callback invoked when the Channel receives new control limit
        values.

        Parameters
        ----------
        which : str
            Which control limit was changed. "UPPER" or "LOWER"
        new_limit : float
            New value for the control limit
        """
        PyDMWritableWidget.ctrl_limit_changed(self, which, new_limit)
        if not self.userDefinedLimits:
            self.reset_slider_limits()

    def update_format_string(self):
        """
        Reconstruct the format string to be used when representing the
        output value.

        Returns
        -------
        format_string : str
            The format string to be used including or not the precision
            and unit
        """
        fs = super(PyDMSlider, self).update_format_string()
        self.update_labels()
        return fs

    def set_enable_state(self):
        """
        Determines wether or not the widget must be enabled or not depending
        on the write access, connection state and presence of limits information
        """
        # Even though by documentation disabling parent QFrame (self), should disable internal
        # slider, in practice it still remains interactive (PyQt 5.12.1). Disabling explicitly, solves
        # the problem.
        should_enable = self._write_access and self._connected and not self._needs_limit_info
        self.setEnabled(should_enable)
        self._slider.setEnabled(should_enable)

    @Slot(int)
    def internal_slider_action_triggered(self, action):
        self.actionTriggered.emit(action)

    @Slot(int)
    def internal_slider_moved(self, val):
        """
        Method invoked when the slider is moved.

        Parameters
        ----------
        val : float
        """
        # Avoid potential crash if limits are undefined
        if self._slider_position_to_value_map is None:
            return
        # The user has moved the slider, we need to update our value.
        # Only update the underlying value, not the self.value property,
        # because we don't need to reset the slider position.    If we change
        # self.value, we can get into a loop where the position changes, which
        # updates the value, which changes the position again, etc etc.
        self.value = self._slider_position_to_value_map[val]
        self.sliderMoved.emit(self.value)

    @Slot()
    def internal_slider_pressed(self):
        """
        Method invoked when the slider is pressed
        """
        self.sliderPressed.emit()

    @Slot()
    def internal_slider_released(self):
        """
        Method invoked when the slider is released
        """
        self.sliderReleased.emit()

    @Slot(int)
    def internal_slider_value_changed(self, val):
        """
        Method invoked when a new value is selected on the slider.
        This will cause the new value to be emitted to the signal
        unless `mute_internal_slider_changes` is True.

        Parameters
        ----------
        val : int
        """
        # At this point, our local copy of the value reflects the position of the
        # slider, now all we need to do is emit a signal to PyDM so that the data
        # plugin will send a put to the channel.  Don't update self.value or self._value
        # in here, it is pointless at best, and could cause an infinite loop at worst.
        if not self._mute_internal_slider_changes:
            self.send_value_signal[float].emit(self.value)

    @Property(bool)
    def showLimitLabels(self):
        """
        Whether or not the high and low limits should be displayed on the slider.

        Returns
        -------
        bool
        """
        return self._show_limit_labels

    @showLimitLabels.setter
    def showLimitLabels(self, checked):
        """
        Whether or not the high and low limits should be displayed on the slider.

        Parameters
        ----------
        checked : bool
        """
        self._show_limit_labels = checked
        if checked:
            self.low_lim_label.show()
            self.high_lim_label.show()
        else:
            self.low_lim_label.hide()
            self.high_lim_label.hide()

    @Property(bool)
    def showValueLabel(self):
        """
        Whether or not the current value should be displayed on the slider.

        Returns
        -------
        bool
        """
        return self._show_value_label

    @showValueLabel.setter
    def showValueLabel(self, checked):
        """
        Whether or not the current value should be displayed on the slider.

        Parameters
        ----------
        checked : bool
        """
        self._show_value_label = checked
        if checked:
            self.value_label.show()
        else:
            self.value_label.hide()

    @Property(QSlider.TickPosition)
    def tickPosition(self):
        """
        Where to draw tick marks for the slider.

        Returns
        -------
        QSlider.TickPosition
        """
        return self._slider.tickPosition()

    @tickPosition.setter
    def tickPosition(self, position):
        """
        Where to draw tick marks for the slider.

        Parameter
        ---------
        position : QSlider.TickPosition
        """
        self._slider.setTickPosition(position)

    @Property(bool)
    def userDefinedLimits(self):
        """
        Wether or not to use limits defined by the user and not from the
        channel

        Returns
        -------
        bool
        """
        return self._user_defined_limits

    @userDefinedLimits.setter
    def userDefinedLimits(self, user_defined_limits):
        """
        Wether or not to use limits defined by the user and not from the
        channel

        Parameters
        ----------
        user_defined_limits : bool
        """
        self._user_defined_limits = user_defined_limits
        self.reset_slider_limits()

    @Property(float)
    def userMinimum(self):
        """
        Lower user defined limit value

        Returns
        -------
        float
        """
        return self._user_minimum

    @userMinimum.setter
    def userMinimum(self, new_min):
        """
        Lower user defined limit value

        Parameters
        ----------
        new_min : float
        """
        self._user_minimum = float(new_min) if new_min is not None else None
        if self.userDefinedLimits:
            self.reset_slider_limits()

    @Property(float)
    def userMaximum(self):
        """
        Upper user defined limit value

        Returns
        -------
        float
        """
        return self._user_maximum

    @userMaximum.setter
    def userMaximum(self, new_max):
        """
        Upper user defined limit value

        Parameters
        ----------
        new_max : float
        """
        self._user_maximum = float(new_max) if new_max is not None else None
        if self.userDefinedLimits:
            self.reset_slider_limits()

    @property
    def minimum(self):
        """
        The current value being used for the lower limit

        Returns
        -------
        float
        """
        if self.userDefinedLimits:
            return self._user_minimum
        return self._lower_ctrl_limit

    @property
    def maximum(self):
        """
        The current value being used for the upper limit

        Returns
        -------
        float
        """
        if self.userDefinedLimits:
            return self._user_maximum
        return self._upper_ctrl_limit

    @Property(int)
    def num_steps(self):
        """
        The number of steps on the slider

        Returns
        -------
        int
        """
        return self._num_steps

    @num_steps.setter
    def num_steps(self, new_steps):
        """
        The number of steps on the slider

        Parameters
        ----------
        new_steps : int
        """
        self._num_steps = int(new_steps)
        self.reset_slider_limits()
Example #22
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
Example #23
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()
class MiscellaneousLauncher(QWidget):
    def __init__(self, parent):
        super().__init__()
        # set title
        self.setWindowTitle(config.thisTranslation["cp4"])
        # set up variables
        self.parent = parent
        # setup interface
        self.setupUI()

    def setupUI(self):
        mainLayout = QGridLayout()
        leftLayout = QVBoxLayout()
        rightLayout = QVBoxLayout()
        self.highLightLauncher = HighlightLauncher(self)
        leftLayout.addWidget(self.highLightLauncher)
        rightLayout.addWidget(self.noteEditor())
        rightLayout.addWidget(self.textToSpeechUtility())
        rightLayout.addWidget(self.utilities())
        rightLayout.addStretch()
        mainLayout.addLayout(leftLayout, 0, 0, 1, 2)
        mainLayout.addLayout(rightLayout, 0, 2, 1, 1)
        self.setLayout(mainLayout)

    def noteEditor(self):
        box = QGroupBox(config.thisTranslation["note_editor"])
        subLayout = QHBoxLayout()
        button = QPushButton(config.thisTranslation["menu7_create"])
        button.setToolTip(config.thisTranslation["menu7_create"])
        button.clicked.connect(self.parent.parent.createNewNoteFile)
        subLayout.addWidget(button)
        button = QPushButton(config.thisTranslation["menu7_open"])
        button.setToolTip(config.thisTranslation["menu7_open"])
        button.clicked.connect(self.parent.parent.openTextFileDialog)
        subLayout.addWidget(button)
        box.setLayout(subLayout)
        return box

    def utilities(self):
        box = QGroupBox(config.thisTranslation["utilities"])
        subLayout = QHBoxLayout()
        button = QPushButton(config.thisTranslation["presentation"])
        button.setToolTip(config.thisTranslation["presentation"])
        button.clicked.connect(
            lambda: self.parent.parent.runPlugin("Presentation"))
        subLayout.addWidget(button)
        if config.isYoutubeDownloaderInstalled:
            button = QPushButton(config.thisTranslation["youtube_utility"])
            button.setToolTip(config.thisTranslation["youtube_utility"])
            button.clicked.connect(self.parent.parent.openYouTube)
            subLayout.addWidget(button)
        box.setLayout(subLayout)
        return box

    def textToSpeechUtility(self):
        box = QGroupBox(config.thisTranslation["tts_utility"])

        layout = QVBoxLayout()

        subLayout = QHBoxLayout()
        self.ttsEdit = QLineEdit()
        self.ttsEdit.setClearButtonEnabled(True)
        self.ttsEdit.setToolTip(config.thisTranslation["enter_text_here"])
        self.ttsEdit.returnPressed.connect(self.speakText)
        subLayout.addWidget(self.ttsEdit)
        layout.addLayout(subLayout)

        self.ttsSlider = QSlider(Qt.Horizontal)
        self.ttsSlider.setToolTip(config.thisTranslation["adjustSpeed"])
        self.ttsSlider.setMinimum(10)
        self.ttsSlider.setMaximum(310)
        self.ttsSlider.setValue(config.espeakSpeed if config.espeak else (
            160 + config.qttsSpeed * 150))
        self.ttsSlider.valueChanged.connect(
            self.changeEspeakSpeed if config.espeak else self.changeQttsSpeed)
        layout.addWidget(self.ttsSlider)

        subLayout = QHBoxLayout()

        self.languageCombo = QComboBox()
        subLayout.addWidget(self.languageCombo)
        if config.espeak:
            languages = TtsLanguages().isoLang2epeakLang
        else:
            languages = TtsLanguages().isoLang2qlocaleLang
        self.languageCodes = list(languages.keys())
        for code in self.languageCodes:
            self.languageCombo.addItem(languages[code][1])
        # Check if selected tts engine has the language user specify.
        if not (config.ttsDefaultLangauge in self.languageCodes):
            config.ttsDefaultLangauge = "en"
        # Set initial index
        # It is essential.  Otherwise, default tts language is changed by defaultTtsLanguageChanged method.
        ttsLanguageIndex = self.languageCodes.index(config.ttsDefaultLangauge)
        self.languageCombo.setCurrentIndex(ttsLanguageIndex)
        # Change default tts language as users select a new language
        self.languageCombo.currentIndexChanged.connect(
            self.defaultTtsLanguageChanged)

        button = QPushButton(config.thisTranslation["speak"])
        button.setToolTip(config.thisTranslation["speak"])
        button.clicked.connect(self.speakText)
        subLayout.addWidget(button)
        button = QPushButton(config.thisTranslation["stop"])
        button.setToolTip(config.thisTranslation["stop"])
        button.clicked.connect(
            self.parent.parent.textCommandParser.stopTtsAudio)
        subLayout.addWidget(button)
        layout.addLayout(subLayout)

        box.setLayout(layout)
        return box

    def defaultTtsLanguageChanged(self, index):
        config.ttsDefaultLangauge = self.languageCodes[index]

    def speakText(self):
        text = self.ttsEdit.text()
        if text:
            if config.isTtsInstalled:
                if ":::" in text:
                    text = text.split(":::")[-1]
                command = "SPEAK:::{0}:::{1}".format(
                    self.languageCodes[self.languageCombo.currentIndex()],
                    text)
                self.parent.isRefreshing = True
                self.parent.runTextCommand(command)
                self.parent.isRefreshing = False
            else:
                self.parent.displayMessage(
                    config.thisTranslation["message_noSupport"])
        else:
            self.parent.displayMessage(
                config.thisTranslation["enterTextFirst"])

    def changeQttsSpeed(self, value):
        config.qttsSpeed = (value * (1.5 / 300) - .5)

    def changeEspeakSpeed(self, value):
        config.espeakSpeed = value

    def refresh(self):
        ttsLanguageIndex = self.languageCodes.index(config.ttsDefaultLangauge)
        self.languageCombo.setCurrentIndex(ttsLanguageIndex)
        self.highLightLauncher.refresh()
Example #25
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.n_dimensional.connect(self._on_n_dim_change)
        self.layer.events.symbol.connect(self._on_symbol_change)
        self.layer.events.size.connect(self._on_size_change)
        self.layer.events.edge_color.connect(self._on_edge_color_change)
        self.layer.events.face_color.connect(self._on_face_color_change)

        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setFixedWidth(110)
        sld.setMinimum(0)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        value = self.layer.size
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value.mean()
        sld.setValue(int(value))
        sld.valueChanged[int].connect(lambda value=sld: self.changeSize(value))
        self.sizeSlider = sld
        self.grid_layout.addWidget(QLabel('size:'), 3, 0)
        self.grid_layout.addWidget(sld, 3, 1)

        face_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            face_comboBox.addItem(c)
        index = face_comboBox.findText(self.layer.face_color,
                                       Qt.MatchFixedString)
        face_comboBox.setCurrentIndex(index)
        face_comboBox.activated[str].connect(
            lambda text=face_comboBox: self.changeFaceColor(text))
        self.faceComboBox = face_comboBox
        self.grid_layout.addWidget(QLabel('face_color:'), 4, 0)
        self.grid_layout.addWidget(face_comboBox, 4, 1)

        edge_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            edge_comboBox.addItem(c)
        index = edge_comboBox.findText(self.layer.edge_color,
                                       Qt.MatchFixedString)
        edge_comboBox.setCurrentIndex(index)
        edge_comboBox.activated[str].connect(
            lambda text=edge_comboBox: self.changeEdgeColor(text))
        self.edgeComboBox = edge_comboBox
        self.grid_layout.addWidget(QLabel('edge_color:'), 5, 0)
        self.grid_layout.addWidget(edge_comboBox, 5, 1)

        symbol_comboBox = QComboBox()
        for s in Symbol:
            symbol_comboBox.addItem(str(s))
        index = symbol_comboBox.findText(self.layer.symbol,
                                         Qt.MatchFixedString)
        symbol_comboBox.setCurrentIndex(index)
        symbol_comboBox.activated[str].connect(
            lambda text=symbol_comboBox: self.changeSymbol(text))
        self.symbolComboBox = symbol_comboBox
        self.grid_layout.addWidget(QLabel('symbol:'), 6, 0)
        self.grid_layout.addWidget(symbol_comboBox, 6, 1)

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip('N-dimensional markers')
        ndim_cb.setChecked(self.layer.n_dimensional)
        ndim_cb.stateChanged.connect(
            lambda state=ndim_cb: self.change_ndim(state))
        self.ndimCheckBox = ndim_cb
        self.grid_layout.addWidget(QLabel('n-dim:'), 7, 0)
        self.grid_layout.addWidget(ndim_cb, 7, 1)

        self.setExpanded(False)
Example #26
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events.n_dimensional.connect(self._on_n_dimensional_change)
        self.layer.events.symbol.connect(self._on_symbol_change)
        self.layer.events.size.connect(self._on_size_change)
        self.layer.events.current_edge_color.connect(
            self._on_current_edge_color_change)
        self.layer.events.current_face_color.connect(
            self._on_current_face_color_change)
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.text.events.visible.connect(self._on_text_visibility_change)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        value = self.layer.current_size
        sld.setValue(int(value))
        sld.valueChanged.connect(self.changeSize)
        self.sizeSlider = sld

        self.faceColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_face_color,
            tooltip='click to set current face color',
        )
        self.edgeColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_edge_color,
            tooltip='click to set current edge color',
        )
        self.faceColorEdit.color_changed.connect(self.changeFaceColor)
        self.edgeColorEdit.color_changed.connect(self.changeEdgeColor)

        symbol_comboBox = QComboBox()
        symbol_comboBox.addItems([str(s) for s in Symbol])
        index = symbol_comboBox.findText(self.layer.symbol,
                                         Qt.MatchFixedString)
        symbol_comboBox.setCurrentIndex(index)
        symbol_comboBox.activated[str].connect(self.changeSymbol)
        self.symbolComboBox = symbol_comboBox

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip('N-dimensional points')
        ndim_cb.setChecked(self.layer.n_dimensional)
        ndim_cb.stateChanged.connect(self.change_ndim)
        self.ndimCheckBox = ndim_cb

        self.select_button = QtModeRadioButton(layer,
                                               'select_points',
                                               Mode.SELECT,
                                               tooltip='Select points')
        self.addition_button = QtModeRadioButton(layer,
                                                 'add_points',
                                                 Mode.ADD,
                                                 tooltip='Add points')
        self.panzoom_button = QtModeRadioButton(layer,
                                                'pan_zoom',
                                                Mode.PAN_ZOOM,
                                                tooltip='Pan/zoom',
                                                checked=True)
        self.delete_button = QtModePushButton(
            layer,
            'delete_shape',
            slot=self.layer.remove_selected,
            tooltip='Delete selected points',
        )

        text_disp_cb = QCheckBox()
        text_disp_cb.setToolTip('toggle text visibility')
        text_disp_cb.setChecked(self.layer.text.visible)
        text_disp_cb.stateChanged.connect(self.change_text_visibility)
        self.textDispCheckBox = text_disp_cb

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.select_button)
        self.button_group.addButton(self.addition_button)
        self.button_group.addButton(self.panzoom_button)

        button_row = QHBoxLayout()
        button_row.addStretch(1)
        button_row.addWidget(self.delete_button)
        button_row.addWidget(self.addition_button)
        button_row.addWidget(self.select_button)
        button_row.addWidget(self.panzoom_button)
        button_row.setContentsMargins(0, 0, 0, 5)
        button_row.setSpacing(4)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_row, 0, 1)
        self.grid_layout.addWidget(QLabel('opacity:'), 1, 0)
        self.grid_layout.addWidget(self.opacitySlider, 1, 1)
        self.grid_layout.addWidget(QLabel('point size:'), 2, 0)
        self.grid_layout.addWidget(self.sizeSlider, 2, 1)
        self.grid_layout.addWidget(QLabel('blending:'), 3, 0)
        self.grid_layout.addWidget(self.blendComboBox, 3, 1)
        self.grid_layout.addWidget(QLabel('symbol:'), 4, 0)
        self.grid_layout.addWidget(self.symbolComboBox, 4, 1)
        self.grid_layout.addWidget(QLabel('face color:'), 5, 0)
        self.grid_layout.addWidget(self.faceColorEdit, 5, 1)
        self.grid_layout.addWidget(QLabel('edge color:'), 6, 0)
        self.grid_layout.addWidget(self.edgeColorEdit, 6, 1)
        self.grid_layout.addWidget(QLabel('display text:'), 7, 0)
        self.grid_layout.addWidget(self.textDispCheckBox, 7, 1)
        self.grid_layout.addWidget(QLabel('n-dim:'), 8, 0)
        self.grid_layout.addWidget(self.ndimCheckBox, 8, 1)
        self.grid_layout.setRowStretch(9, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)
Example #27
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.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.editingFinished.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()

    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
Example #28
0
class QtTracksControls(QtLayerControls):
    """Qt view and controls for the Tracks layer.

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

    Attributes
    ----------
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : layers.Tracks
        An instance of a Tracks layer.

    """

    layer: 'napari.layers.Tracks'

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

        # NOTE(arl): there are no events fired for changing checkboxes
        self.layer.events.tail_width.connect(self._on_tail_width_change)
        self.layer.events.tail_length.connect(self._on_tail_length_change)
        self.layer.events.head_length.connect(self._on_head_length_change)
        self.layer.events.properties.connect(self._on_properties_change)
        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.color_by.connect(self._on_color_by_change)

        # combo box for track coloring, we can get these from the properties
        # keys
        self.color_by_combobox = QComboBox()
        self.color_by_combobox.addItems(self.layer.properties_to_color_by)

        self.colormap_combobox = QComboBox()
        for name, colormap in AVAILABLE_COLORMAPS.items():
            display_name = colormap._display_name
            self.colormap_combobox.addItem(display_name, name)

        # slider for track head length
        self.head_length_slider = QSlider(Qt.Horizontal)
        self.head_length_slider.setFocusPolicy(Qt.NoFocus)
        self.head_length_slider.setMinimum(0)
        self.head_length_slider.setMaximum(self.layer._max_length)
        self.head_length_slider.setSingleStep(1)

        # slider for track tail length
        self.tail_length_slider = QSlider(Qt.Horizontal)
        self.tail_length_slider.setFocusPolicy(Qt.NoFocus)
        self.tail_length_slider.setMinimum(1)
        self.tail_length_slider.setMaximum(self.layer._max_length)
        self.tail_length_slider.setSingleStep(1)

        # slider for track edge width
        self.tail_width_slider = QSlider(Qt.Horizontal)
        self.tail_width_slider.setFocusPolicy(Qt.NoFocus)
        self.tail_width_slider.setMinimum(1)
        self.tail_width_slider.setMaximum(int(2 * self.layer._max_width))
        self.tail_width_slider.setSingleStep(1)

        # checkboxes for display
        self.id_checkbox = QCheckBox()
        self.tail_checkbox = QCheckBox()
        self.tail_checkbox.setChecked(True)
        self.graph_checkbox = QCheckBox()
        self.graph_checkbox.setChecked(True)

        self.tail_width_slider.valueChanged.connect(self.change_tail_width)
        self.tail_length_slider.valueChanged.connect(self.change_tail_length)
        self.head_length_slider.valueChanged.connect(self.change_head_length)
        self.tail_checkbox.stateChanged.connect(self.change_display_tail)
        self.id_checkbox.stateChanged.connect(self.change_display_id)
        self.graph_checkbox.stateChanged.connect(self.change_display_graph)
        self.color_by_combobox.currentTextChanged.connect(self.change_color_by)
        self.colormap_combobox.currentTextChanged.connect(self.change_colormap)

        self.layout().addRow(trans._('color by:'), self.color_by_combobox)
        self.layout().addRow(trans._('colormap:'), self.colormap_combobox)
        self.layout().addRow(trans._('blending:'), self.blendComboBox)
        self.layout().addRow(trans._('opacity:'), self.opacitySlider)
        self.layout().addRow(trans._('tail width:'), self.tail_width_slider)
        self.layout().addRow(trans._('tail length:'), self.tail_length_slider)
        self.layout().addRow(trans._('head length:'), self.head_length_slider)
        self.layout().addRow(trans._('tail:'), self.tail_checkbox)
        self.layout().addRow(trans._('show ID:'), self.id_checkbox)
        self.layout().addRow(trans._('graph:'), self.graph_checkbox)

        self._on_tail_length_change()
        self._on_tail_width_change()
        self._on_colormap_change()
        self._on_color_by_change()

    def _on_tail_width_change(self):
        """Receive layer model track line width change event and update slider."""
        with self.layer.events.tail_width.blocker():
            value = int(2 * self.layer.tail_width)
            self.tail_width_slider.setValue(value)

    def _on_tail_length_change(self):
        """Receive layer model track line width change event and update slider."""
        with self.layer.events.tail_length.blocker():
            value = self.layer.tail_length
            self.tail_length_slider.setValue(value)

    def _on_head_length_change(self):
        """Receive layer model track line width change event and update slider."""
        with self.layer.events.head_length.blocker():
            value = self.layer.head_length
            self.head_length_slider.setValue(value)

    def _on_properties_change(self):
        """Change the properties that can be used to color the tracks."""
        with self.layer.events.properties.blocker():

            with qt_signals_blocked(self.color_by_combobox):
                self.color_by_combobox.clear()
            self.color_by_combobox.addItems(self.layer.properties_to_color_by)

    def _on_colormap_change(self):
        """Receive layer model colormap change event and update combobox."""
        with self.layer.events.colormap.blocker():
            self.colormap_combobox.setCurrentIndex(
                self.colormap_combobox.findData(self.layer.colormap))

    def _on_color_by_change(self):
        """Receive layer model color_by change event and update combobox."""
        with self.layer.events.color_by.blocker():
            color_by = self.layer.color_by

            idx = self.color_by_combobox.findText(color_by,
                                                  Qt.MatchFixedString)
            self.color_by_combobox.setCurrentIndex(idx)

    def change_tail_width(self, value):
        """Change track line width of shapes on the layer model.

        Parameters
        ----------
        value : float
            Line width of track tails.
        """
        self.layer.tail_width = float(value) / 2.0

    def change_tail_length(self, value):
        """Change edge line backward length of shapes on the layer model.

        Parameters
        ----------
        value : int
            Line length of track tails.
        """
        self.layer.tail_length = value

    def change_head_length(self, value):
        """Change edge line forward length of shapes on the layer model.

        Parameters
        ----------
        value : int
            Line length of track tails.
        """
        self.layer.head_length = value

    def change_display_tail(self, state):
        self.layer.display_tail = self.tail_checkbox.isChecked()

    def change_display_id(self, state):
        self.layer.display_id = self.id_checkbox.isChecked()

    def change_display_graph(self, state):
        self.layer.display_graph = self.graph_checkbox.isChecked()

    def change_color_by(self, value: str):
        self.layer.color_by = value

    def change_colormap(self, colormap: str):
        self.layer.colormap = self.colormap_combobox.currentData()
Example #29
0
class QtTracksControls(QtLayerControls):
    """Qt view and controls for the Tracks layer.

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

    Attributes
    ----------
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : layers.Tracks
        An instance of a Tracks layer.

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

        # NOTE(arl): there are no events fired for changing checkboxes
        self.layer.events.tail_width.connect(self._on_tail_width_change)
        self.layer.events.tail_length.connect(self._on_tail_length_change)
        self.layer.events.properties.connect(self._on_properties_change)
        self.layer.events.colormap.connect(self._on_colormap_change)
        self.layer.events.color_by.connect(self._on_color_by_change)

        # combo box for track coloring, we can get these from the properties
        # keys
        self.color_by_combobox = QComboBox()
        self.color_by_combobox.addItems(self.layer.properties_to_color_by)

        self.colormap_combobox = QComboBox()
        for name, colormap in AVAILABLE_COLORMAPS.items():
            display_name = colormap._display_name
            self.colormap_combobox.addItem(display_name, name)

        # slider for track tail length
        self.tail_length_slider = QSlider(Qt.Horizontal)
        self.tail_length_slider.setFocusPolicy(Qt.NoFocus)
        self.tail_length_slider.setMinimum(1)
        self.tail_length_slider.setMaximum(MAX_TAIL_LENGTH)
        self.tail_length_slider.setSingleStep(1)

        # slider for track edge width
        self.tail_width_slider = QSlider(Qt.Horizontal)
        self.tail_width_slider.setFocusPolicy(Qt.NoFocus)
        self.tail_width_slider.setMinimum(1)
        self.tail_width_slider.setMaximum(MAX_TAIL_WIDTH)
        self.tail_width_slider.setSingleStep(1)

        # checkboxes for display
        self.id_checkbox = QCheckBox()
        self.tail_checkbox = QCheckBox()
        self.tail_checkbox.setChecked(True)
        self.graph_checkbox = QCheckBox()
        self.graph_checkbox.setChecked(True)

        self.tail_width_slider.valueChanged.connect(self.change_tail_width)
        self.tail_length_slider.valueChanged.connect(self.change_tail_length)
        self.tail_checkbox.stateChanged.connect(self.change_display_tail)
        self.id_checkbox.stateChanged.connect(self.change_display_id)
        self.graph_checkbox.stateChanged.connect(self.change_display_graph)
        self.color_by_combobox.currentTextChanged.connect(self.change_color_by)
        self.colormap_combobox.currentTextChanged.connect(self.change_colormap)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])

        self.grid_layout.addWidget(QLabel(trans._('color by:')), 0, 0)
        self.grid_layout.addWidget(self.color_by_combobox, 0, 1)
        self.grid_layout.addWidget(QLabel(trans._('colormap:')), 1, 0)
        self.grid_layout.addWidget(self.colormap_combobox, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 2, 0)
        self.grid_layout.addWidget(self.blendComboBox, 2, 1)
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 3, 0)
        self.grid_layout.addWidget(self.opacitySlider, 3, 1)
        self.grid_layout.addWidget(QLabel(trans._('tail width:')), 4, 0)
        self.grid_layout.addWidget(self.tail_width_slider, 4, 1)
        self.grid_layout.addWidget(QLabel(trans._('tail length:')), 5, 0)
        self.grid_layout.addWidget(self.tail_length_slider, 5, 1)
        self.grid_layout.addWidget(QLabel(trans._('tail:')), 6, 0)
        self.grid_layout.addWidget(self.tail_checkbox, 6, 1)
        self.grid_layout.addWidget(QLabel(trans._('show ID:')), 7, 0)
        self.grid_layout.addWidget(self.id_checkbox, 7, 1)
        self.grid_layout.addWidget(QLabel(trans._('graph:')), 8, 0)
        self.grid_layout.addWidget(self.graph_checkbox, 8, 1)
        self.grid_layout.setRowStretch(9, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

        self._on_tail_length_change()
        self._on_tail_width_change()
        self._on_colormap_change()
        self._on_color_by_change()

    def _on_tail_width_change(self, event=None):
        """Receive layer model track line width change event and update slider.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context, by default None.
        """
        with self.layer.events.tail_width.blocker():
            value = self.layer.tail_width
            value = np.clip(int(2 * value), 1, MAX_TAIL_WIDTH)
            self.tail_width_slider.setValue(value)

    def _on_tail_length_change(self, event=None):
        """Receive layer model track line width change event and update slider.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context, by default None.
        """
        with self.layer.events.tail_length.blocker():
            value = self.layer.tail_length
            value = np.clip(value, 1, MAX_TAIL_LENGTH)
            self.tail_length_slider.setValue(value)

    def _on_properties_change(self, event=None):
        """Change the properties that can be used to color the tracks."""
        with self.layer.events.properties.blocker():

            with qt_signals_blocked(self.color_by_combobox):
                self.color_by_combobox.clear()
            self.color_by_combobox.addItems(self.layer.properties_to_color_by)

    def _on_colormap_change(self, event=None):
        """Receive layer model colormap change event and update combobox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context, by default None.
        """
        with self.layer.events.colormap.blocker():
            self.colormap_combobox.setCurrentIndex(
                self.colormap_combobox.findData(self.layer.colormap))

    def _on_color_by_change(self, event=None):
        """Receive layer model color_by change event and update combobox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context, by default None.
        """
        with self.layer.events.color_by.blocker():
            color_by = self.layer.color_by

            idx = self.color_by_combobox.findText(color_by,
                                                  Qt.MatchFixedString)
            self.color_by_combobox.setCurrentIndex(idx)

    def change_tail_width(self, value):
        """Change track line width of shapes on the layer model.

        Parameters
        ----------
        value : float
            Line width of track tails.
        """
        self.layer.tail_width = float(value) / 2.0

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

        Parameters
        ----------
        value : int
            Line length of track tails.
        """
        self.layer.tail_length = value

    def change_display_tail(self, state):
        self.layer.display_tail = self.tail_checkbox.isChecked()

    def change_display_id(self, state):
        self.layer.display_id = self.id_checkbox.isChecked()

    def change_display_graph(self, state):
        self.layer.display_graph = self.graph_checkbox.isChecked()

    def change_color_by(self, value: str):
        self.layer.color_by = value

    def change_colormap(self, colormap: str):
        self.layer.colormap = self.colormap_combobox.currentData()
Example #30
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.interpolation.connect(self._on_interpolation_change)
        self.layer.events.rendering.connect(self._on_rendering_change)
        self.layer.events.iso_threshold.connect(self._on_iso_threshold_change)
        self.layer.events.attenuation.connect(self._on_attenuation_change)
        self.layer.dims.events.ndisplay.connect(self._on_ndisplay_change)

        self.interpComboBox = QComboBox(self)
        self.interpComboBox.activated[str].connect(self.changeInterpolation)
        self.interpLabel = QLabel('interpolation:')

        renderComboBox = QComboBox(self)
        renderComboBox.addItems(Rendering.keys())
        index = renderComboBox.findText(
            self.layer.rendering, Qt.MatchFixedString
        )
        renderComboBox.setCurrentIndex(index)
        renderComboBox.activated[str].connect(self.changeRendering)
        self.renderComboBox = renderComboBox
        self.renderLabel = QLabel('rendering:')

        sld = QSlider(Qt.Horizontal, parent=self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        sld.setValue(int(self.layer.iso_threshold * 100))
        sld.valueChanged.connect(self.changeIsoThreshold)
        self.isoThresholdSlider = sld
        self.isoThresholdLabel = QLabel('iso threshold:')

        sld = QSlider(Qt.Horizontal, parent=self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        sld.setValue(int(self.layer.attenuation * 200))
        sld.valueChanged.connect(self.changeAttenuation)
        self.attenuationSlider = sld
        self.attenuationLabel = QLabel('attenuation:')
        self._on_ndisplay_change()

        colormap_layout = QHBoxLayout()
        colormap_layout.addWidget(self.colorbarLabel)
        colormap_layout.addWidget(self.colormapComboBox)
        colormap_layout.addStretch(1)

        # 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)
        self.grid_layout.addWidget(QLabel('contrast limits:'), 1, 0)
        self.grid_layout.addWidget(self.contrastLimitsSlider, 1, 1)
        self.grid_layout.addWidget(QLabel('gamma:'), 2, 0)
        self.grid_layout.addWidget(self.gammaSlider, 2, 1)
        self.grid_layout.addWidget(QLabel('colormap:'), 3, 0)
        self.grid_layout.addLayout(colormap_layout, 3, 1)
        self.grid_layout.addWidget(QLabel('blending:'), 4, 0)
        self.grid_layout.addWidget(self.blendComboBox, 4, 1)
        self.grid_layout.addWidget(self.interpLabel, 5, 0)
        self.grid_layout.addWidget(self.interpComboBox, 5, 1)
        self.grid_layout.addWidget(self.renderLabel, 6, 0)
        self.grid_layout.addWidget(self.renderComboBox, 6, 1)
        self.grid_layout.addWidget(self.isoThresholdLabel, 7, 0)
        self.grid_layout.addWidget(self.isoThresholdSlider, 7, 1)
        self.grid_layout.addWidget(self.attenuationLabel, 8, 0)
        self.grid_layout.addWidget(self.attenuationSlider, 8, 1)
        self.grid_layout.setRowStretch(9, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)
Example #31
0
    def __init__(self, layer):
        super().__init__()

        self.layer = layer
        layer.events.select.connect(lambda v: self.setSelected(True))
        layer.events.deselect.connect(lambda v: self.setSelected(False))
        layer.events.name.connect(self._on_layer_name_change)
        layer.events.blending.connect(self._on_blending_change)
        layer.events.opacity.connect(self._on_opacity_change)
        layer.events.visible.connect(self._on_visible_change)
        layer.events.thumbnail.connect(self._on_thumbnail_change)

        self.setObjectName('layer')

        self.vbox_layout = QVBoxLayout()
        self.top = QFrame()
        self.top_layout = QHBoxLayout()
        self.grid = QFrame()
        self.grid_layout = QGridLayout()
        self.vbox_layout.addWidget(self.top)
        self.vbox_layout.addWidget(self.grid)
        self.vbox_layout.setSpacing(0)
        self.top.setFixedHeight(38)
        self.top_layout.setContentsMargins(0, 0, 0, 0)
        self.grid_layout.setContentsMargins(0, 0, 0, 0)
        self.top_layout.setAlignment(Qt.AlignCenter)
        self.top.setLayout(self.top_layout)
        self.grid.setLayout(self.grid_layout)
        self.setLayout(self.vbox_layout)

        self.name_column = 0
        self.property_column = 1

        cb = QCheckBox(self)
        cb.setObjectName('visibility')
        cb.setToolTip('Layer visibility')
        cb.setChecked(self.layer.visible)
        cb.setProperty('mode', 'visibility')
        cb.stateChanged.connect(lambda state=cb: self.changeVisible(state))
        self.visibleCheckBox = cb
        self.top_layout.addWidget(cb)

        tb = QLabel(self)
        tb.setObjectName('thumbmnail')
        tb.setToolTip('Layer thumbmnail')
        self.thumbnail_label = tb
        self._on_thumbnail_change(None)
        self.top_layout.addWidget(tb)

        textbox = QLineEdit(self)
        textbox.setText(layer.name)
        textbox.home(False)
        textbox.setToolTip('Layer name')
        textbox.setAcceptDrops(False)
        textbox.setEnabled(True)
        textbox.editingFinished.connect(self.changeText)
        self.nameTextBox = textbox
        self.top_layout.addWidget(textbox)

        pb = QPushButton(self)
        pb.setToolTip('Expand properties')
        pb.clicked.connect(self.changeExpanded)
        pb.setObjectName('expand')
        self.expand_button = pb
        self.top_layout.addWidget(pb)

        row = self.grid_layout.rowCount()
        sld = QSlider(Qt.Horizontal, self)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(100)
        sld.setSingleStep(1)
        sld.setValue(self.layer.opacity * 100)
        sld.valueChanged[int].connect(
            lambda value=sld: self.changeOpacity(value))
        self.opacitySilder = sld
        row = self.grid_layout.rowCount()
        self.grid_layout.addWidget(QLabel('opacity:'), row, self.name_column)
        self.grid_layout.addWidget(sld, row, self.property_column)

        row = self.grid_layout.rowCount()
        blend_comboBox = QComboBox()
        for blend in Blending:
            blend_comboBox.addItem(str(blend))
        index = blend_comboBox.findText(self.layer.blending,
                                        Qt.MatchFixedString)
        blend_comboBox.setCurrentIndex(index)
        blend_comboBox.activated[str].connect(
            lambda text=blend_comboBox: self.changeBlending(text))
        self.blendComboBox = blend_comboBox
        self.grid_layout.addWidget(QLabel('blending:'), row, self.name_column)
        self.grid_layout.addWidget(blend_comboBox, row, self.property_column)

        msg = 'Click to select\nDrag to rearrange\nDouble click to expand'
        self.setToolTip(msg)
        self.setExpanded(False)
        self.setFixedWidth(250)
        self.grid_layout.setColumnMinimumWidth(0, 100)
        self.grid_layout.setColumnMinimumWidth(1, 100)

        self.setSelected(self.layer.selected)
Example #32
0
class QtSizeSliderPreviewWidget(QWidget):
    """
    Widget displaying a description, textedit and slider to adjust font size
    with preview.

    Parameters
    ----------
    parent : qtpy.QtWidgets.QWidget, optional
        Default is None.
    description : str, optional
        Default is "".
    preview_text : str, optional
        Default is "".
    value : int, optional
        Default is None.
    min_value : int, optional
        Default is 1.
    max_value : int, optional
        Default is 50.
    unit : str, optional
        Default is "px".
    """

    valueChanged = Signal(int)

    def __init__(
        self,
        parent: QWidget = None,
        description: str = None,
        preview_text: str = None,
        value: int = None,
        min_value: int = 1,
        max_value: int = 50,
        unit: str = "px",
    ):
        super().__init__(parent)

        description = description or ""
        preview_text = preview_text or ""
        self._value = value if value else self.fontMetrics().height()
        self._min_value = min_value
        self._max_value = max_value

        # Widget
        self._lineedit = QLineEdit()
        self._description_label = QLabel(self)
        self._unit_label = QLabel(self)
        self._slider = QSlider(Qt.Horizontal, self)
        self._slider_min_label = QLabel(self)
        self._slider_max_label = QLabel(self)
        self._preview = QtFontSizePreview(self)
        self._preview_label = QLabel(self)
        self._validator = None

        # Widgets setup
        self._description_label.setText(description)
        self._description_label.setWordWrap(True)
        self._unit_label.setText(unit)
        self._lineedit.setAlignment(Qt.AlignRight)
        self._slider_min_label.setText(str(min_value))
        self._slider_max_label.setText(str(max_value))
        self._slider.setMinimum(min_value)
        self._slider.setMaximum(max_value)
        self._preview.setText(preview_text)
        self._preview_label.setText(trans._("preview"))
        self._preview_label.setAlignment(Qt.AlignHCenter)
        self.setFocusProxy(self._lineedit)

        # Layout
        left_bottom_layout = QHBoxLayout()
        left_bottom_layout.addWidget(self._lineedit)
        left_bottom_layout.addWidget(self._unit_label)
        left_bottom_layout.addWidget(self._slider_min_label)
        left_bottom_layout.addWidget(self._slider)
        left_bottom_layout.addWidget(self._slider_max_label)

        left_layout = QVBoxLayout()
        left_layout.addWidget(self._description_label)
        left_layout.addLayout(left_bottom_layout)

        right_layout = QVBoxLayout()
        right_layout.addWidget(self._preview)
        right_layout.addWidget(self._preview_label)

        layout = QHBoxLayout()
        layout.addLayout(left_layout, 2)
        layout.addLayout(right_layout, 1)

        self.setLayout(layout)

        # Signals
        self._slider.valueChanged.connect(self._update_value)
        self._lineedit.textChanged.connect(self._update_value)

        self._update_line_width()
        self._update_validator()
        self._update_value(self._value)

    def _update_validator(self):
        self._validator = QIntValidator(self._min_value, self._max_value, self)
        self._lineedit.setValidator(self._validator)

    def _update_line_width(self):
        """Update width ofg line text edit."""
        size = self._lineedit.fontMetrics().horizontalAdvance(
            "m" * (1 + len(str(self._max_value))))
        self._lineedit.setMaximumWidth(size)
        self._lineedit.setMinimumWidth(size)

    def _update_value(self, value: int):
        """Update internal value and emit if changed."""
        if value == "":
            value = int(self._value)

        value = int(value)

        if value > self._max_value:
            value = self._max_value
        elif value < self._min_value:
            value = self._min_value

        if value != self._value:
            self.valueChanged.emit(value)

        self._value = value
        self._refresh(self._value)

    def _refresh(self, value: int = None):
        """Refresh the value on all subwidgets."""
        value = value if value else self._value
        self.blockSignals(True)
        self._lineedit.setText(str(value))
        self._slider.setValue(value)
        font = QFont()
        font.setPixelSize(value)
        self._preview.setFont(font)

        font = QFont()
        font.setPixelSize(self.fontMetrics().height() - 4)
        self._preview_label.setFont(font)

        self.blockSignals(False)

    def description(self) -> str:
        """Return the current widget description.

        Returns
        -------
        str
            The description text.
        """
        return self._description_label.text()

    def setDescription(self, text: str):
        """Set the current widget description.

        Parameters
        ----------
        text : str
            The description text.
        """
        self._description_label.setText(text)

    def previewText(self) -> str:
        """Return the current preview text.

        Returns
        -------
        str
            The current preview text.
        """
        return self._preview.text()

    def setPreviewText(self, text: str):
        """Set the current preview text.

        Parameters
        ----------
        text : str
            The current preview text.
        """
        self._preview.setText(text)

    def unit(self) -> str:
        """Return the current unit text.

        Returns
        -------
        str
            The current unit text.
        """
        return self._unit_label.text()

    def setUnit(self, text: str):
        """Set the current unit text.

        Parameters
        ----------
        text : str
            The current preview text.
        """
        self._unit_label.setText(text)

    def minimum(self) -> int:
        """Return the current minimum value for the slider and value in textbox.

        Returns
        -------
        int
            The minimum value for the slider.
        """
        return self._min_value

    def setMinimum(self, value: int):
        """Set the current minimum value for the slider and value in textbox.

        Parameters
        ----------
        value : int
            The minimum value for the slider.
        """
        value = int(value)
        if value < self._max_value:
            self._min_value = value
            self._value = (self._min_value
                           if self._value < self._min_value else self._value)
            self._slider_min_label.setText(str(value))
            self._slider.setMinimum(value)
            self._update_validator()
            self._refresh()
        else:
            raise ValueError(
                trans._("Minimum value must be smaller than {}".format(
                    self._max_value)))

    def maximum(self) -> int:
        """Return the maximum value for the slider and value in textbox.

        Returns
        -------
        int
            The maximum value for the slider.
        """
        return self._max_value

    def setMaximum(self, value: int):
        """Set the maximum value for the slider and value in textbox.

        Parameters
        ----------
        value : int
            The maximum value for the slider.
        """
        value = int(value)
        if value > self._min_value:
            self._max_value = value
            self._value = (self._max_value
                           if self._value > self._max_value else self._value)
            self._slider_max_label.setText(str(value))
            self._slider.setMaximum(value)
            self._update_validator()
            self._update_line_width()
            self._refresh()
        else:
            raise ValueError(
                trans._("Maximum value must be larger than {}".format(
                    self._min_value)))

    def value(self) -> int:
        """Return the current widget value.

        Returns
        -------
        int
            The current value.
        """
        return self._value

    def setValue(self, value: int):
        """Set the current widget value.

        Parameters
        ----------
        value : int
            The current value.
        """
        self._update_value(value)
Example #33
0
class PyDMSlider(QFrame, PyDMWritableWidget):
    """
    A QSlider with support for Channels and more from PyDM.

    Parameters
    ----------
    parent : QWidget
        The parent widget for the Label
    init_channel : str, optional
        The channel to be used by the widget.
    """
    actionTriggered = Signal(int)
    rangeChanged = Signal(float, float)
    sliderMoved = Signal(float)
    sliderPressed = Signal()
    sliderReleased = Signal()
    valueChanged = Signal(float)

    def __init__(self, parent=None, init_channel=None):
        QFrame.__init__(self, parent)
        PyDMWritableWidget.__init__(self, init_channel=init_channel)
        self.alarmSensitiveContent = True
        self.alarmSensitiveBorder = False
        # Internal values for properties
        self.set_enable_state()
        self._show_limit_labels = True
        self._show_value_label = True
        self._user_defined_limits = False
        self._needs_limit_info = True
        self._minimum = None
        self._maximum = None
        self._user_minimum = -10.0
        self._user_maximum = 10.0
        self._num_steps = 101
        self._orientation = Qt.Horizontal
        # Set up all the internal widgets that make up a PyDMSlider.
        # We'll add all these things to layouts when we call setup_widgets_for_orientation
        label_size_policy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
        self.low_lim_label = QLabel(self)
        self.low_lim_label.setObjectName("lowLimLabel")
        self.low_lim_label.setSizePolicy(label_size_policy)
        self.low_lim_label.setAlignment(Qt.AlignLeft | Qt.AlignTrailing
                                        | Qt.AlignVCenter)
        self.value_label = QLabel(self)
        self.value_label.setObjectName("valueLabel")
        self.value_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.high_lim_label = QLabel(self)
        self.high_lim_label.setObjectName("highLimLabel")
        self.high_lim_label.setSizePolicy(label_size_policy)
        self.high_lim_label.setAlignment(Qt.AlignRight | Qt.AlignTrailing
                                         | Qt.AlignVCenter)
        self._slider = QSlider(parent=self)
        self._slider.setOrientation(Qt.Horizontal)
        self._slider.sliderMoved.connect(self.internal_slider_moved)
        self._slider.sliderPressed.connect(self.internal_slider_pressed)
        self._slider.sliderReleased.connect(self.internal_slider_released)
        self._slider.valueChanged.connect(self.internal_slider_value_changed)
        # self.vertical_layout.addWidget(self._slider)
        # Other internal variables and final setup steps
        self._slider_position_to_value_map = None
        self._mute_internal_slider_changes = False
        self.setup_widgets_for_orientation(self._orientation)
        self.reset_slider_limits()

    def init_for_designer(self):
        """
        Method called after the constructor to tweak configurations for
        when using the widget with the Qt Designer
        """
        self.value = 0.0

    @Property(Qt.Orientation)
    def orientation(self):
        """
        The slider orientation (Horizontal or Vertical)

        Returns
        -------
        int
            Qt.Horizontal or Qt.Vertical
        """
        return self._orientation

    @orientation.setter
    def orientation(self, new_orientation):
        """
        The slider orientation (Horizontal or Vertical)

        Parameters
        ----------
        new_orientation : int
            Qt.Horizontal or Qt.Vertical
        """
        self._orientation = new_orientation
        self.setup_widgets_for_orientation(new_orientation)

    def setup_widgets_for_orientation(self, new_orientation):
        """
        Reconstruct the widget given the orientation.

        Parameters
        ----------
        new_orientation : int
            Qt.Horizontal or Qt.Vertical
        """
        if new_orientation not in (Qt.Horizontal, Qt.Vertical):
            logger.error(
                "Invalid orientation '{0}'. The existing layout will not change."
                .format(new_orientation))
            return

        layout = None
        if new_orientation == Qt.Horizontal:
            layout = QVBoxLayout()
            layout.setContentsMargins(4, 0, 4, 4)
            label_layout = QHBoxLayout()
            label_layout.addWidget(self.low_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.high_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)
        elif new_orientation == Qt.Vertical:
            layout = QHBoxLayout()
            layout.setContentsMargins(0, 4, 4, 4)
            label_layout = QVBoxLayout()
            label_layout.addWidget(self.high_lim_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.value_label)
            label_layout.addStretch(0)
            label_layout.addWidget(self.low_lim_label)
            layout.addLayout(label_layout)
            self._slider.setOrientation(new_orientation)
            layout.addWidget(self._slider)

        if self.layout() is not None:
            # Trick to remove the existing layout by re-parenting it in an empty widget.
            QWidget().setLayout(self.layout())
        self.setLayout(layout)

    def update_labels(self):
        """
        Update the limits and value labels with the correct values.
        """
        def set_label(value, label_widget):
            if value is None:
                label_widget.setText("")
            else:
                label_widget.setText(self.format_string.format(value))

        set_label(self.minimum, self.low_lim_label)
        set_label(self.maximum, self.high_lim_label)
        set_label(self.value, self.value_label)

    def reset_slider_limits(self):
        """
        Reset the limits and adjust the labels properly for the slider.
        """
        if self.minimum is None or self.maximum is None:
            self._needs_limit_info = True
            self.set_enable_state()
            return
        self._needs_limit_info = False
        self._slider.setMinimum(0)
        self._slider.setMaximum(self._num_steps - 1)
        self._slider.setSingleStep(1)
        self._slider.setPageStep(10)
        self._slider_position_to_value_map = np.linspace(self.minimum,
                                                         self.maximum,
                                                         num=self._num_steps)
        self.update_labels()
        self.set_slider_to_closest_value(self.value)
        self.rangeChanged.emit(self.minimum, self.maximum)
        self.set_enable_state()

    def find_closest_slider_position_to_value(self, val):
        """
        Find and returns the index for the closest position on the slider
        for a given value.

        Parameters
        ----------
        val : float

        Returns
        -------
        int
        """
        diff = abs(self._slider_position_to_value_map - float(val))
        return np.argmin(diff)

    def set_slider_to_closest_value(self, val):
        """
        Set the value for the slider according to a given value.

        Parameters
        ----------
        val : float
        """
        if val is None or self._needs_limit_info:
            return
        # When we set the slider to the closest value, it may end up at a slightly
        # different position than val (if val is not in self._slider_position_to_value_map)
        # We don't want that slight difference to get broacast out and put the channel
        # somewhere new.    For example, if the slider can only be at 0.4 or 0.5, but a
        # new value comes in of 0.45, its more important to keep the 0.45 than to change
        # it to where the slider gets set.  Therefore, we mute the internal slider changes
        # so that its valueChanged signal doesn't cause us to emit a signal to PyDM to change
        # the value of the channel.
        self._mute_internal_slider_changes = True
        self._slider.setValue(self.find_closest_slider_position_to_value(val))
        self._mute_internal_slider_changes = False

    def value_changed(self, new_val):
        """
        Callback invoked when the Channel value is changed.

        Parameters
        ----------
        new_val : int or float
            The new value from the channel.
        """
        PyDMWritableWidget.value_changed(self, new_val)
        if hasattr(self, "value_label"):
            self.value_label.setText(self.format_string.format(self.value))
        if not self._slider.isSliderDown():
            self.set_slider_to_closest_value(self.value)

    def ctrl_limit_changed(self, which, new_limit):
        """
        Callback invoked when the Channel receives new control limit
        values.

        Parameters
        ----------
        which : str
            Which control limit was changed. "UPPER" or "LOWER"
        new_limit : float
            New value for the control limit
        """
        PyDMWritableWidget.ctrl_limit_changed(self, which, new_limit)
        if not self.userDefinedLimits:
            self.reset_slider_limits()

    def update_format_string(self):
        """
        Reconstruct the format string to be used when representing the
        output value.

        Returns
        -------
        format_string : str
            The format string to be used including or not the precision
            and unit
        """
        fs = PyDMWritableWidget.update_format_string(self)
        self.update_labels()
        return fs

    def set_enable_state(self):
        """
        Determines wether or not the widget must be enabled or not depending
        on the write access, connection state and presence of limits information
        """
        self.setEnabled(self._write_access and self._connected
                        and not self._needs_limit_info)

    @Slot(int)
    def internal_slider_action_triggered(self, action):
        self.actionTriggered.emit(action)

    @Slot(int)
    def internal_slider_moved(self, val):
        """
        Method invoked when the slider is moved.

        Parameters
        ----------
        val : float
        """
        # The user has moved the slider, we need to update our value.
        # Only update the underlying value, not the self.value property,
        # because we don't need to reset the slider position.    If we change
        # self.value, we can get into a loop where the position changes, which
        # updates the value, which changes the position again, etc etc.
        self.value = self._slider_position_to_value_map[val]
        self.sliderMoved.emit(self.value)

    @Slot()
    def internal_slider_pressed(self):
        """
        Method invoked when the slider is pressed
        """
        self.sliderPressed.emit()

    @Slot()
    def internal_slider_released(self):
        """
        Method invoked when the slider is released
        """
        self.sliderReleased.emit()

    @Slot(int)
    def internal_slider_value_changed(self, val):
        """
        Method invoked when a new value is selected on the slider.
        This will cause the new value to be emitted to the signal
        unless `mute_internal_slider_changes` is True.

        Parameters
        ----------
        val : int
        """
        # At this point, our local copy of the value reflects the position of the
        # slider, now all we need to do is emit a signal to PyDM so that the data
        # plugin will send a put to the channel.  Don't update self.value or self._value
        # in here, it is pointless at best, and could cause an infinite loop at worst.
        if not self._mute_internal_slider_changes:
            self.send_value_signal[float].emit(self.value)

    @Property(bool)
    def showLimitLabels(self):
        """
        Whether or not the high and low limits should be displayed on the slider.

        Returns
        -------
        bool
        """
        return self._show_limit_labels

    @showLimitLabels.setter
    def showLimitLabels(self, checked):
        """
        Whether or not the high and low limits should be displayed on the slider.

        Parameters
        ----------
        checked : bool
        """
        self._show_limit_labels = checked
        if checked:
            self.low_lim_label.show()
            self.high_lim_label.show()
        else:
            self.low_lim_label.hide()
            self.high_lim_label.hide()

    @Property(bool)
    def showValueLabel(self):
        """
        Whether or not the current value should be displayed on the slider.

        Returns
        -------
        bool
        """
        return self._show_value_label

    @showValueLabel.setter
    def showValueLabel(self, checked):
        """
        Whether or not the current value should be displayed on the slider.

        Parameters
        ----------
        checked : bool
        """
        self._show_value_label = checked
        if checked:
            self.value_label.show()
        else:
            self.value_label.hide()

    @Property(QSlider.TickPosition)
    def tickPosition(self):
        """
        Where to draw tick marks for the slider.

        Returns
        -------
        QSlider.TickPosition
        """
        return self._slider.tickPosition()

    @tickPosition.setter
    def tickPosition(self, position):
        """
        Where to draw tick marks for the slider.

        Parameter
        ---------
        position : QSlider.TickPosition
        """
        self._slider.setTickPosition(position)

    @Property(bool)
    def userDefinedLimits(self):
        """
        Wether or not to use limits defined by the user and not from the
        channel

        Returns
        -------
        bool
        """
        return self._user_defined_limits

    @userDefinedLimits.setter
    def userDefinedLimits(self, user_defined_limits):
        """
        Wether or not to use limits defined by the user and not from the
        channel

        Parameters
        ----------
        user_defined_limits : bool
        """
        self._user_defined_limits = user_defined_limits
        self.reset_slider_limits()

    @Property(float)
    def userMinimum(self):
        """
        Lower user defined limit value

        Returns
        -------
        float
        """
        return self._user_minimum

    @userMinimum.setter
    def userMinimum(self, new_min):
        """
        Lower user defined limit value

        Parameters
        ----------
        new_min : float
        """
        self._user_minimum = float(new_min) if new_min is not None else None
        if self.userDefinedLimits:
            self.reset_slider_limits()

    @Property(float)
    def userMaximum(self):
        """
        Upper user defined limit value

        Returns
        -------
        float
        """
        return self._user_maximum

    @userMaximum.setter
    def userMaximum(self, new_max):
        """
        Upper user defined limit value

        Parameters
        ----------
        new_max : float
        """
        self._user_maximum = float(new_max) if new_max is not None else None
        if self.userDefinedLimits:
            self.reset_slider_limits()

    @property
    def minimum(self):
        """
        The current value being used for the lower limit

        Returns
        -------
        float
        """
        if self.userDefinedLimits:
            return self._user_minimum
        return self._lower_ctrl_limit

    @property
    def maximum(self):
        """
        The current value being used for the upper limit

        Returns
        -------
        float
        """
        if self.userDefinedLimits:
            return self._user_maximum
        return self._upper_ctrl_limit

    @Property(int)
    def num_steps(self):
        """
        The number of steps on the slider

        Returns
        -------
        int
        """
        return self._num_steps

    @num_steps.setter
    def num_steps(self, new_steps):
        """
        The number of steps on the slider

        Parameters
        ----------
        new_steps : int
        """
        self._num_steps = int(new_steps)
        self.reset_slider_limits()
Example #34
0
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events.edge_width.connect(self._on_edge_width_change)
        self.layer.events.current_edge_color.connect(
            self._on_current_edge_color_change
        )
        self.layer.events.current_face_color.connect(
            self._on_current_face_color_change
        )
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.text.events.visible.connect(self._on_text_visibility_change)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(0)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        value = self.layer.current_edge_width
        if isinstance(value, Iterable):
            if isinstance(value, list):
                value = np.asarray(value)
            value = value.mean()
        sld.setValue(int(value))
        sld.valueChanged.connect(self.changeWidth)
        self.widthSlider = sld

        def _radio_button(
            parent,
            btn_name,
            mode,
            action_name,
            extra_tooltip_text='',
            **kwargs,
        ):
            """
            Convenience local function to create a RadioButton and bind it to
            an action at the same time.

            Parameters
            ----------
            parent : Any
                Parent of the generated QtModeRadioButton
            btn_name : str
                name fo the button
            mode : Enum
                Value Associated to current button
            action_name : str
                Action triggered when button pressed
            extra_tooltip_text : str
                Text you want added after the automatic tooltip set by the
                action manager
            **kwargs:
                Passed to QtModeRadioButton

            Returns
            -------
            button: QtModeRadioButton
                button bound (or that will be bound to) to action `action_name`

            Notes
            -----
            When shortcuts are modifed/added/removed via the action manager, the
            tooltip will be updated to reflect the new shortcut.
            """
            action_name = 'napari:' + action_name
            btn = QtModeRadioButton(parent, btn_name, mode, **kwargs)
            action_manager.bind_button(
                action_name,
                btn,
                extra_tooltip_text='',
            )
            return btn

        self.select_button = _radio_button(
            layer, 'select', Mode.SELECT, "activate_select_mode"
        )

        self.direct_button = _radio_button(
            layer, 'direct', Mode.DIRECT, "activate_direct_mode"
        )

        self.panzoom_button = _radio_button(
            layer,
            'zoom',
            Mode.PAN_ZOOM,
            "napari:activate_shape_pan_zoom_mode",
            extra_tooltip_text=trans._('(or hold Space)'),
            checked=True,
        )

        self.rectangle_button = _radio_button(
            layer,
            'rectangle',
            Mode.ADD_RECTANGLE,
            "activate_add_rectangle_mode",
        )
        self.ellipse_button = _radio_button(
            layer,
            'ellipse',
            Mode.ADD_ELLIPSE,
            "activate_add_ellipse_mode",
        )

        self.line_button = _radio_button(
            layer, 'line', Mode.ADD_LINE, "activate_add_line_mode"
        )
        self.path_button = _radio_button(
            layer, 'path', Mode.ADD_PATH, "activate_add_path_mode"
        )
        self.polygon_button = _radio_button(
            layer,
            'polygon',
            Mode.ADD_POLYGON,
            "activate_add_polygon_mode",
        )
        self.vertex_insert_button = _radio_button(
            layer,
            'vertex_insert',
            Mode.VERTEX_INSERT,
            "activate_vertex_insert_mode",
        )
        self.vertex_remove_button = _radio_button(
            layer,
            'vertex_remove',
            Mode.VERTEX_REMOVE,
            "activate_vertex_remove_mode",
        )

        self.move_front_button = QtModePushButton(
            layer,
            'move_front',
            slot=self.layer.move_to_front,
            tooltip=trans._('Move to front'),
        )

        action_manager.bind_button(
            'napari:move_shapes_selection_to_front', self.move_front_button
        )

        self.move_back_button = QtModePushButton(
            layer,
            'move_back',
            slot=self.layer.move_to_back,
            tooltip=trans._('Move to back'),
        )
        action_manager.bind_button(
            'napari:move_shapes_selection_to_back', self.move_back_button
        )

        self.delete_button = QtModePushButton(
            layer,
            'delete_shape',
            slot=self.layer.remove_selected,
            tooltip=trans._(
                "Delete selected shapes ({shortcut})",
                shortcut=Shortcut('Backspace').platform,
            ),
        )

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.select_button)
        self.button_group.addButton(self.direct_button)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.rectangle_button)
        self.button_group.addButton(self.ellipse_button)
        self.button_group.addButton(self.line_button)
        self.button_group.addButton(self.path_button)
        self.button_group.addButton(self.polygon_button)
        self.button_group.addButton(self.vertex_insert_button)
        self.button_group.addButton(self.vertex_remove_button)

        button_grid = QGridLayout()
        button_grid.addWidget(self.vertex_remove_button, 0, 2)
        button_grid.addWidget(self.vertex_insert_button, 0, 3)
        button_grid.addWidget(self.delete_button, 0, 4)
        button_grid.addWidget(self.direct_button, 0, 5)
        button_grid.addWidget(self.select_button, 0, 6)
        button_grid.addWidget(self.panzoom_button, 0, 7)
        button_grid.addWidget(self.move_back_button, 1, 1)
        button_grid.addWidget(self.move_front_button, 1, 2)
        button_grid.addWidget(self.ellipse_button, 1, 3)
        button_grid.addWidget(self.rectangle_button, 1, 4)
        button_grid.addWidget(self.polygon_button, 1, 5)
        button_grid.addWidget(self.line_button, 1, 6)
        button_grid.addWidget(self.path_button, 1, 7)
        button_grid.setContentsMargins(5, 0, 0, 5)
        button_grid.setColumnStretch(0, 1)
        button_grid.setSpacing(4)

        self.faceColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_face_color,
            tooltip=trans._('click to set current face color'),
        )
        self._on_current_face_color_change()
        self.edgeColorEdit = QColorSwatchEdit(
            initial_color=self.layer.current_edge_color,
            tooltip=trans._('click to set current edge color'),
        )
        self._on_current_edge_color_change()
        self.faceColorEdit.color_changed.connect(self.changeFaceColor)
        self.edgeColorEdit.color_changed.connect(self.changeEdgeColor)

        text_disp_cb = QCheckBox()
        text_disp_cb.setToolTip(trans._('toggle text visibility'))
        text_disp_cb.setChecked(self.layer.text.visible)
        text_disp_cb.stateChanged.connect(self.change_text_visibility)
        self.textDispCheckBox = text_disp_cb

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_grid, 0, 0, 1, 2)
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 1, 0)
        self.grid_layout.addWidget(self.opacitySlider, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('edge width:')), 2, 0)
        self.grid_layout.addWidget(self.widthSlider, 2, 1)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 3, 0)
        self.grid_layout.addWidget(self.blendComboBox, 3, 1)
        self.grid_layout.addWidget(QLabel(trans._('face color:')), 4, 0)
        self.grid_layout.addWidget(self.faceColorEdit, 4, 1)
        self.grid_layout.addWidget(QLabel(trans._('edge color:')), 5, 0)
        self.grid_layout.addWidget(self.edgeColorEdit, 5, 1)
        self.grid_layout.addWidget(QLabel(trans._('display text:')), 6, 0)
        self.grid_layout.addWidget(self.textDispCheckBox, 6, 1)
        self.grid_layout.setRowStretch(7, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)
Example #35
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)