コード例 #1
0
ファイル: toolbar.py プロジェクト: pyhmsa/pyhmsa-gui
class _SaveDialog(QFileDialog):

    def __init__(self, parent):
        QFileDialog.__init__(self, parent)
        self.setFileMode(QFileDialog.AnyFile)
        self.setAcceptMode(QFileDialog.AcceptSave)

        # Widgets
        self._chk_tight = QCheckBox('Tight layout')

        self._txt_dpi = QSpinBox()
        self._txt_dpi.setRange(1, 10000)
        self._txt_dpi.setSingleStep(50)
        self._txt_dpi.setSuffix('dpi')
        self._txt_dpi.setValue(100)

        # Layouts
        layout = self.layout()

        lyt_extras = QHBoxLayout()
        lyt_extras.addWidget(QLabel('Extra options'))
        lyt_extras.addWidget(self._chk_tight)
        lyt_extras.addWidget(QLabel('Resolution'))
        lyt_extras.addWidget(self._txt_dpi)
        layout.addLayout(lyt_extras, layout.rowCount(), 0, 1, layout.columnCount())

        self.setLayout(layout)

    def tightLayout(self):
        return self._chk_tight.isChecked()

    def setTightLayout(self, tight):
        self._chk_tight.setChecked(tight)

    def dpi(self):
        return self._txt_dpi.value()

    def setDpi(self, dpi):
        self._txt_dpi.setValue(dpi)
コード例 #2
0
class FigureBrowser(QWidget):
    """
    Widget to browse the figures that were sent by the kernel to the IPython
    console to be plotted inline.
    """
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()

    def __init__(self,
                 parent=None,
                 options_button=None,
                 plugin_actions=[],
                 background_color=None):
        super(FigureBrowser, self).__init__(parent)

        self.shellwidget = None
        self.is_visible = True
        self.figviewer = None
        self.setup_in_progress = False
        self.background_color = background_color

        # Options :
        self.mute_inline_plotting = None
        self.show_plot_outline = None

        # Option actions :
        self.mute_inline_action = None
        self.show_plot_outline_action = None

        self.options_button = options_button
        self.plugin_actions = plugin_actions
        self.shortcuts = self.create_shortcuts()

    def setup(self, mute_inline_plotting=None, show_plot_outline=None):
        """Setup the figure browser with provided settings."""
        assert self.shellwidget is not None

        self.mute_inline_plotting = mute_inline_plotting
        self.show_plot_outline = show_plot_outline

        if self.figviewer is not None:
            self.mute_inline_action.setChecked(mute_inline_plotting)
            self.show_plot_outline_action.setChecked(show_plot_outline)
            return

        self.figviewer = FigureViewer(background_color=self.background_color)
        self.figviewer.setStyleSheet("FigureViewer{"
                                     "border: 1px solid lightgrey;"
                                     "border-top-width: 0px;"
                                     "border-bottom-width: 0px;"
                                     "border-left-width: 0px;"
                                     "}")
        self.thumbnails_sb = ThumbnailScrollBar(
            self.figviewer, background_color=self.background_color)

        # Option actions :
        self.setup_option_actions(mute_inline_plotting, show_plot_outline)

        # Create the layout :
        main_widget = QSplitter()
        main_widget.addWidget(self.figviewer)
        main_widget.addWidget(self.thumbnails_sb)
        main_widget.setFrameStyle(QScrollArea().frameStyle())

        self.tools_layout = QHBoxLayout()
        toolbar = self.setup_toolbar()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        layout = create_plugin_layout(self.tools_layout, main_widget)
        self.setLayout(layout)

    def setup_toolbar(self):
        """Setup the toolbar"""
        savefig_btn = create_toolbutton(self,
                                        icon=ima.icon('filesave'),
                                        tip=_("Save Image As..."),
                                        triggered=self.save_figure)

        saveall_btn = create_toolbutton(self,
                                        icon=ima.icon('save_all'),
                                        tip=_("Save All Images..."),
                                        triggered=self.save_all_figures)

        copyfig_btn = create_toolbutton(
            self,
            icon=ima.icon('editcopy'),
            tip=_("Copy plot to clipboard as image (%s)" %
                  get_shortcut('plots', 'copy')),
            triggered=self.copy_figure)

        closefig_btn = create_toolbutton(self,
                                         icon=ima.icon('editclear'),
                                         tip=_("Remove image"),
                                         triggered=self.close_figure)

        closeall_btn = create_toolbutton(
            self,
            icon=ima.icon('filecloseall'),
            tip=_("Remove all images from the explorer"),
            triggered=self.close_all_figures)

        vsep1 = QFrame()
        vsep1.setFrameStyle(53)

        goback_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowBack'),
                                       tip=_("Previous Figure ({})".format(
                                           get_shortcut(
                                               'plots', 'previous figure'))),
                                       triggered=self.go_previous_thumbnail)

        gonext_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowForward'),
                                       tip=_("Next Figure ({})".format(
                                           get_shortcut(
                                               'plots', 'next figure'))),
                                       triggered=self.go_next_thumbnail)

        vsep2 = QFrame()
        vsep2.setFrameStyle(53)

        zoom_out_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_out'),
            tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
            triggered=self.zoom_out)

        zoom_in_btn = create_toolbutton(
            self,
            icon=ima.icon('zoom_in'),
            tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
            triggered=self.zoom_in)

        self.zoom_disp = QSpinBox()
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(zoom_out_btn)
        layout.addWidget(zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [
            savefig_btn, saveall_btn, copyfig_btn, closefig_btn, closeall_btn,
            vsep1, goback_btn, gonext_btn, vsep2, zoom_pan
        ]

    def setup_option_actions(self, mute_inline_plotting, show_plot_outline):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True
        self.mute_inline_action = create_action(
            self,
            _("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda state: self.option_changed('mute_inline_plotting',
                                                      state))
        self.mute_inline_action.setChecked(mute_inline_plotting)

        self.show_plot_outline_action = create_action(
            self,
            _("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=self.show_fig_outline_in_viewer)
        self.show_plot_outline_action.setChecked(show_plot_outline)

        self.actions = [self.mute_inline_action, self.show_plot_outline_action]
        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            # When the FigureBowser widget is instatiated outside of the
            # plugin (for testing purpose for instance), we need to create
            # the options_button and set its menu.
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(self.tools_layout.count() - 1,
                                           self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def create_shortcuts(self):
        """Create shortcuts for this widget."""
        # Configurable
        copyfig = config_shortcut(self.copy_figure,
                                  context='plots',
                                  name='copy',
                                  parent=self)
        prevfig = config_shortcut(self.go_previous_thumbnail,
                                  context='plots',
                                  name='previous figure',
                                  parent=self)
        nextfig = config_shortcut(self.go_next_thumbnail,
                                  context='plots',
                                  name='next figure',
                                  parent=self)

        return [copyfig, prevfig, nextfig]

    def get_shortcut_data(self):
        """
        Return shortcut data, a list of tuples (shortcut, text, default).

        shortcut (QShortcut or QAction instance)
        text (string): action/shortcut description
        default (string): default key sequence
        """
        return [sc.data for sc in self.shortcuts]

    def option_changed(self, option, value):
        """Handle when the value of an option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        if self.setup_in_progress is False:
            self.sig_option_changed.emit(option, value)

    def show_fig_outline_in_viewer(self, state):
        """Draw a frame around the figure viewer if state is True."""
        if state is True:
            self.figviewer.figcanvas.setStyleSheet(
                "FigureCanvas{border: 1px solid lightgrey;}")
        else:
            self.figviewer.figcanvas.setStyleSheet("FigureCanvas{}")
        self.option_changed('show_plot_outline', state)

    def set_shellwidget(self, shellwidget):
        """Bind the shellwidget instance to the figure browser"""
        self.shellwidget = shellwidget
        shellwidget.set_figurebrowser(self)
        shellwidget.sig_new_inline_figure.connect(self._handle_new_figure)

    def get_actions(self):
        """Get the actions of the widget."""
        return self.actions

    def _handle_new_figure(self, fig, fmt):
        """
        Handle when a new figure is sent to the IPython console by the
        kernel.
        """
        self.thumbnails_sb.add_thumbnail(fig, fmt)

    # ---- Toolbar Handlers
    def zoom_in(self):
        """Zoom the figure in by a single step in the figure viewer."""
        self.figviewer.zoom_in()

    def zoom_out(self):
        """Zoom the figure out by a single step in the figure viewer."""
        self.figviewer.zoom_out()

    def go_previous_thumbnail(self):
        """
        Select the thumbnail previous to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_previous_thumbnail()

    def go_next_thumbnail(self):
        """
        Select the thumbnail next to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_next_thumbnail()

    def save_figure(self):
        """Save the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.save_current_figure_as()

    def save_all_figures(self):
        """Save all the figures in a selected directory."""
        return self.thumbnails_sb.save_all_figures_as()

    def close_figure(self):
        """Close the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_current_thumbnail()

    def close_all_figures(self):
        """Close all the figures in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_all_thumbnails()

    def copy_figure(self):
        """Copy figure from figviewer to clipboard."""
        if self.figviewer and self.figviewer.figcanvas.fig:
            self.figviewer.figcanvas.copy_figure()
コード例 #3
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()
コード例 #4
0
ファイル: preferences.py プロジェクト: zchlrnr/pyNastran
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self.dim_max = data['dim_max']

        # font size for menu
        self._default_font_size = FONT_SIZE
        self._default_text_size = TEXT_SIZE

        # an annotation is the marked/probe label
        self._default_annotation_size = ANNOTATION_SIZE

        self._default_coord_scale = COORD_SCALE * 100. # * self.dim_max
        self._default_coord_text_scale = COORD_TEXT_SCALE * 100. # * self.dim_max
        self._default_clipping_min = data['min_clip']
        self._default_clipping_max = data['max_clip']
        #self._default_annotation_size = data['annotation_size'] # int
        #self.default_magnify = data['magnify']

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

        #self.out_data = data

        # doesn't include dim_max
        self._picker_size = data['picker_size'] * 100.
        self._coord_scale = data['coord_scale'] * 100.
        self._coord_text_scale = data['coord_text_scale'] * 100.

        self._magnify = data['magnify']
        self._text_size = data['text_size']
        self._highlight_opacity = data['highlight_opacity']

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

        self._nastran_is_element_quality = data['nastran_is_element_quality']
        self._nastran_is_properties = data['nastran_is_properties']
        self._nastran_is_3d_bars = data['nastran_is_3d_bars']
        self._nastran_is_3d_bars_update = data['nastran_is_3d_bars_update']
        self._nastran_is_bar_axes = data['nastran_is_bar_axes']
        self._nastran_create_coords = data['nastran_create_coords']
        self._nastran_is_shell_mcids = data['nastran_is_shell_mcids']

        self._nastran_stress = data['nastran_stress']
        self._nastran_plate_stress = data['nastran_plate_stress']
        self._nastran_composite_plate_stress = data['nastran_composite_plate_stress']
        self._nastran_strain = data['nastran_strain']
        self._nastran_plate_strain = data['nastran_plate_strain']
        self._nastran_composite_plate_strain = data['nastran_composite_plate_strain']
        self._nastran_rod_stress = data['nastran_rod_stress']
        self._nastran_bar_stress = data['nastran_bar_stress']
        self._nastran_beam_stress = data['nastran_beam_stress']
        self._nastran_rod_strain = data['nastran_rod_strain']
        self._nastran_bar_strain = data['nastran_bar_strain']
        self._nastran_beam_strain = data['nastran_beam_strain']


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

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

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

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

        #-----------------------------------------------------------------------
        # Highlight Color
        self.highlight_opacity_label = QLabel("Highlight Opacity:")
        self.highlight_opacity_edit = QDoubleSpinBox(self)
        self.highlight_opacity_edit.setValue(self._highlight_opacity)
        self.highlight_opacity_edit.setRange(0.1, 1.0)
        self.highlight_opacity_edit.setDecimals(1)
        self.highlight_opacity_edit.setSingleStep(0.1)
        self.highlight_opacity_button = QPushButton("Default")

        # Text Color
        self.highlight_color_label = QLabel("Highlight Color:")
        self.highlight_color_edit = QPushButtonColor(self.highlight_color_int)

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

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

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

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

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

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

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

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

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

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

        self.coord_scale_edit = QDoubleSpinBox(self)
        self.coord_scale_edit.setRange(0.1, 1000.)
        self.coord_scale_edit.setDecimals(3)
        self.coord_scale_edit.setSingleStep(1.0)
        self.coord_scale_edit.setValue(self._coord_scale)

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

        self.coord_text_scale_edit = QDoubleSpinBox(self)
        self.coord_text_scale_edit.setRange(0.1, 2000.)
        self.coord_text_scale_edit.setDecimals(3)
        self.coord_text_scale_edit.setSingleStep(2.)
        self.coord_text_scale_edit.setValue(self._coord_text_scale)

        # Show corner coord
        self.corner_coord_label = QLabel("Show Corner Coordinate System:")
        self.corner_coord_checkbox = QCheckBox()
        self.corner_coord_checkbox.setChecked(self._show_corner_coord)

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

        #-----------------------------------------------------------------------
        self.nastran_is_element_quality_checkbox = QCheckBox('Element Quality')
        self.nastran_is_element_quality_checkbox.setToolTip('Cacluate Aspect Ratio, Skew Angle, Max/Min Interior Angle, etc.')
        self.nastran_is_element_quality_checkbox.setChecked(self._nastran_is_element_quality)

        self.nastran_is_properties_checkbox = QCheckBox('Properties')
        self.nastran_is_properties_checkbox.setToolTip('Breakdown each layer of a PCOMP/PSHELL')
        self.nastran_is_properties_checkbox.setChecked(self._nastran_is_properties)

        self.nastran_is_3d_bars_checkbox = QCheckBox('3D Bars')
        self.nastran_is_3d_bars_checkbox.setToolTip('Crete 3D Bar/Beam geometry')
        self.nastran_is_3d_bars_checkbox.setChecked(self._nastran_is_3d_bars)
        #self.nastran_is_3d_bars_checkbox.setDisabled(True)

        self.nastran_is_3d_bars_update_checkbox = QCheckBox('Update 3D Bars')
        self.nastran_is_3d_bars_update_checkbox.setToolTip('Update the 3D Bar/Beam cross-sections when deformations are applied')
        self.nastran_is_3d_bars_update_checkbox.setChecked(self._nastran_is_3d_bars_update)

        self.nastran_is_shell_mcid_checkbox = QCheckBox('Shell MCIDs')
        self.nastran_is_shell_mcid_checkbox.setToolTip('Calculate the Material Coordinate Systems for Shells')
        self.nastran_is_shell_mcid_checkbox.setChecked(self._nastran_is_shell_mcids)

        self.nastran_create_coords_checkbox = QCheckBox('Coords')
        self.nastran_create_coords_checkbox.setChecked(self._nastran_create_coords)

        self.nastran_is_bar_axes_checkbox = QCheckBox('Bar Axes')
        self.nastran_is_bar_axes_checkbox.setChecked(self._nastran_is_bar_axes)
        #self.nastran_is_bar_axes_checkbox.setDisabled(True)

        if 0:
            self.nastran_stress_checkbox = QCheckBox('Stress')
            self.nastran_plate_stress_checkbox = QCheckBox('Plate Stress')
            self.nastran_composite_plate_stress_checkbox = QCheckBox('Composite Plate Stress')
            self.nastran_rod_stress_checkbox = QCheckBox('Rod Stress')
            self.nastran_bar_stress_checkbox = QCheckBox('Bar Stress')
            self.nastran_beam_stress_checkbox = QCheckBox('Beam Stress')

            self.nastran_stress_checkbox.setChecked(self._nastran_stress)
            self.nastran_plate_stress_checkbox.setChecked(self._nastran_plate_stress)
            self.nastran_composite_plate_stress_checkbox.setChecked(self._nastran_composite_plate_stress)
            self.nastran_rod_stress_checkbox.setChecked(self._nastran_rod_stress)
            self.nastran_bar_stress_checkbox.setChecked(self._nastran_bar_stress)
            self.nastran_beam_stress_checkbox.setChecked(self._nastran_beam_stress)

            self.nastran_strain_checkbox = QCheckBox('Strain')
            self.nastran_plate_strain_checkbox = QCheckBox('Plate Strain')
            self.nastran_composite_plate_strain_checkbox = QCheckBox('Composite Plate Strain')
            self.nastran_rod_strain_checkbox = QCheckBox('Rod Strain')
            self.nastran_bar_strain_checkbox = QCheckBox('Bar Strain')
            self.nastran_beam_strain_checkbox = QCheckBox('Beam Strain')

            self.nastran_strain_checkbox.setChecked(self._nastran_strain)
            self.nastran_plate_strain_checkbox.setChecked(self._nastran_plate_strain)
            self.nastran_composite_plate_strain_checkbox.setChecked(self._nastran_composite_plate_strain)
            self.nastran_rod_strain_checkbox.setChecked(self._nastran_rod_strain)
            self.nastran_bar_strain_checkbox.setChecked(self._nastran_bar_strain)
            self.nastran_beam_strain_checkbox.setChecked(self._nastran_beam_strain)

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

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

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

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

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

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

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

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

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

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

    def create_layout(self):
        grid = QGridLayout()

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

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

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

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

        grid.addWidget(self.highlight_color_label, irow, 0)
        grid.addWidget(self.highlight_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.highlight_opacity_label, irow, 0)
        grid.addWidget(self.highlight_opacity_edit, irow, 1)
        irow += 1

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

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

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

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

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

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

        grid.addWidget(self.corner_coord_label, irow, 0)
        grid.addWidget(self.corner_coord_checkbox, irow, 1)
        irow += 1

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

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

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

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

        #--------------------------------------------------
        grid_nastran = QGridLayout()
        irow = 0

        grid_nastran.addWidget(self.nastran_create_coords_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_element_quality_checkbox, irow, 0)
        grid_nastran.addWidget(self.nastran_is_properties_checkbox, irow, 1)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_bar_axes_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_shell_mcid_checkbox, irow, 0)
        irow += 1

        grid_nastran.addWidget(self.nastran_is_3d_bars_checkbox, irow, 0)
        grid_nastran.addWidget(self.nastran_is_3d_bars_update_checkbox, irow, 1)
        irow += 1

        #bold_font = make_font(self._default_font_size, is_bold=True)
        vbox_nastran = QVBoxLayout()
        self.nastran_label = QLabel('Nastran:')
        vbox_nastran.addWidget(self.nastran_label)
        vbox_nastran.addLayout(grid_nastran)

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

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

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

    def set_connections(self):
        """creates the actions for the menu"""
        self.font_size_button.clicked.connect(self.on_default_font_size)
        self.font_size_edit.valueChanged.connect(self.on_font)

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

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

        self.highlight_color_edit.clicked.connect(self.on_highlight_color)
        self.highlight_opacity_edit.valueChanged.connect(self.on_highlight_opacity)

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

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

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

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

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

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

        #------------------------------------
        # format-specific
        self.nastran_is_element_quality_checkbox.clicked.connect(self.on_nastran_is_element_quality)
        self.nastran_is_properties_checkbox.clicked.connect(self.on_nastran_is_properties)
        self.nastran_is_3d_bars_checkbox.clicked.connect(self.on_nastran_is_3d_bars)
        self.nastran_is_3d_bars_update_checkbox.clicked.connect(self.on_nastran_is_3d_bars_update)
        self.nastran_is_bar_axes_checkbox.clicked.connect(self.on_nastran_is_bar_axes)
        self.nastran_create_coords_checkbox.clicked.connect(self.on_nastran_create_coords)
        self.nastran_is_shell_mcid_checkbox.clicked.connect(self.on_nastran_is_shell_mcids)

        #self.nastran_is_shell_mcid_checkbox.clicked.connect(self.on_nastran_is_shell_mcids2)
        #------------------------------------

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

    def on_nastran_is_element_quality(self):
        """set the nastran element quality preferences"""
        is_checked = self.nastran_is_element_quality_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_element_quality = is_checked
    def on_nastran_is_properties(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_properties_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_properties = is_checked
    def on_nastran_is_3d_bars(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_3d_bars_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_3d_bars = is_checked
    def on_nastran_is_3d_bars_update(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_3d_bars_update_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_3d_bars_update = is_checked
    def on_nastran_is_bar_axes(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_bar_axes_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_bar_axes = is_checked
    def on_nastran_create_coords(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_create_coords_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_create_coords = is_checked
    def on_nastran_is_shell_mcids(self):
        """set the nastran properties preferences"""
        is_checked = self.nastran_is_shell_mcid_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.settings.nastran_is_shell_mcids = is_checked

    #def on_nastran_is_shell_mcids2(self):
        #"""set the nastran properties preferences"""
        #is_checked = self.nastran_is_shell_mcid_checkbox.isChecked()
        #if self.win_parent is not None:
            #self.win_parent.settings.nastran_is_shell_mcids = is_checked

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

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

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

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

    def on_corner_coord(self):
        is_checked = self.corner_coord_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.set_corner_axis_visiblity(is_checked, render=True)

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

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

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

    def on_highlight_color(self):
        """ Choose a highlight color"""
        title = "Choose a highlight color"
        rgb_color_ints = self.highlight_color_int
        color_edit = self.highlight_color_edit
        func_name = 'set_highlight_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.highlight_color_int = rgb_color_ints
            self.highlight_color_float = rgb_color_floats

    def on_highlight_opacity(self, value=None):
        if value is None:
            value = self.highlight_opacity_edit.value()
        self._highlight_opacity = value
        if self.win_parent is not None:
            self.win_parent.settings.set_highlight_opacity(value)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
コード例 #5
0
ファイル: node.py プロジェクト: zhenhaochu/pyNastran
class EditNodeProperties(QDialog):
    def __init__(self, data, win_parent=None):
        """
        +-----------------+
        | Edit Node Props |
        +-----------------+------+
        |  LEwingTip             |
        |  Node2                 |
        |  Node3                 |
        |  Node4                 |
        |                        |
        |  All Nodes:            |
        |    Color     red       |
        |    PointSize 3         |
        |    Opacity   0.3       |
        |    Show/Hide           |
        |                        |
        |  Name        LEwingTip |
        |  Location    X Y Z     |
        |  Coord       0         |
        |  CoordType   R, C, S   |
        |                        |
        |   Previous     Next    |
        |                        |
        |          Close         |
        +------------------------+
        """
        QDialog.__init__(self, win_parent)
        self.setWindowTitle('Edit Node Properties')

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

        point_properties = data['point_properties']
        print(point_properties)
        #name = point_properties.name
        point_size = point_properties.point_size
        opacity = point_properties.opacity
        color = point_properties.color
        show = point_properties.is_visible

        self.points = data['points']

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

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

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

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

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

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

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

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

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

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

        self.all_nodes_header = QLabel("All Nodes:")
        self.point_size = QLabel("Point Size:")
        self.point_size_edit = QSpinBox(self)
        self.point_size_edit.setRange(1, 10)
        self.point_size_edit.setSingleStep(1)
        self.point_size_edit.setValue(point_size)

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

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

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

        self.description = QLabel("Description:")
        self.description_edit = QLineEdit(str(description))
        #self.description_edit.setDisabled(True)

        location_x = 0.1
        location_y = 0.1
        location_z = 0.1
        self.location = QLabel("Location:")
        self.location_x_edit = QDoubleSpinBox(self)
        self.location_y_edit = QDoubleSpinBox(self)
        self.location_z_edit = QDoubleSpinBox(self)
        #self.location_x_edit.setDecimals(1)
        delta_x = abs(location_x) / 100. if location_x != 0.0 else 0.1
        delta_y = abs(location_y) / 100. if location_y != 0.0 else 0.1
        delta_z = abs(location_z) / 100. if location_z != 0.0 else 0.1
        self.location_x_edit.setSingleStep(delta_x)
        self.location_y_edit.setSingleStep(delta_y)
        self.location_z_edit.setSingleStep(delta_z)
        self.location_x_edit.setValue(location_x)
        self.location_y_edit.setValue(location_y)
        self.location_z_edit.setValue(location_z)

        self.coord = QLabel("Coord:")
        self.coord_edit = QSpinBox(self)
        self.coord_edit.setRange(0, 99999999)
        #self.coord_edit.setSingleStep(1)
        self.coord_edit.setValue(0)

        self.coord_type = QLabel("Coord Type:")
        #----------------------------------------------

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

        self.close_button = QPushButton("Close")

        self.create_layout()
        self.set_connections()

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

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

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

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

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

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

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

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

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

        grid1 = QGridLayout()
        grid2 = QGridLayout()

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

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

        location_layout = QHBoxLayout()
        location_layout.addWidget(self.location_x_edit)
        location_layout.addWidget(self.location_y_edit)
        location_layout.addWidget(self.location_z_edit)

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

        vbox1 = QVBoxLayout()
        vbox1.addWidget(self.checkbox_show)
        vbox1.addWidget(self.checkbox_hide)
        #vbox1.addLayout(checkboxs)

        #-----------------------------------------
        irow = 0
        grid1.addWidget(self.all_nodes_header, irow, 0)
        irow += 1

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

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

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

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

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

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

        #|  All Nodes:            |
        #|    Color     red       |
        #|    PointSize 3         |
        #|    Opacity   0.3       |
        #|    Show/Hide           |
        #|                        |
        #|  Name        LEwingTip |
        #|  Location    X Y Z     |
        #|  Coord       0         |
        #|  CoordType   R, C, S   |
        #|                        |
        #|   Previous     Next    |
        grid2.addWidget(self.coord, irow, 0)
        grid2.addWidget(self.coord_edit, irow, 1)
        irow += 1

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

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

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

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

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

    def set_connections(self):
        """creates the actions for the menu"""
        self.opacity_edit.valueChanged.connect(self.on_opacity)
        #self.connect(self.point_size, QtCore.SIGNAL('clicked()'), self.on_point_size)
        #self.point_size_edit.clicked.connect(self.on_point_size)  # need to update name??
        self.color_edit.clicked.connect(self.on_color)
        self.checkbox_show.clicked.connect(self.on_show)
        self.checkbox_hide.clicked.connect(self.on_hide)

        self.description_edit.textEdited.connect(
            self.on_description)  # valueChanged????
        self.coord_edit.valueChanged.connect(self.on_coord)
        self.radio_rectangular.clicked.connect(self.on_coord_type)
        self.radio_cylindrical.clicked.connect(self.on_coord_type)
        self.radio_spherical.clicked.connect(self.on_coord_type)

        self.location_x_edit.valueChanged.connect(self.on_location_x)
        self.location_y_edit.valueChanged.connect(self.on_location_y)
        self.location_z_edit.valueChanged.connect(self.on_location_z)
        #self.connect(self.check_apply, QtCore.SIGNAL('clicked()'), self.on_check_apply)
        #self.connect(self.apply_button, QtCore.SIGNAL('clicked()'), self.on_apply)
        #self.connect(self.ok_button, QtCore.SIGNAL('clicked()'), self.on_ok)
        self.close_button.clicked.connect(self.on_close)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_close(self):
        self.out_data['clicked_close'] = True
        self.close()
コード例 #6
0
ファイル: main_widget.py プロジェクト: wakafired/spyder
class PlotsWidget(PluginMainWidget):
    DEFAULT_OPTIONS = {
        'auto_fit_plotting': True,
        'mute_inline_plotting': True,
        'show_plot_outline': True,
        'save_dir': getcwd_or_home()
    }

    # Signals
    sig_option_changed = Signal(str, object)

    sig_figure_loaded = Signal()
    """This signal is emitted when a figure is loaded succesfully"""

    sig_redirect_stdio_requested = Signal(bool)
    """
    This signal is emitted to request the main application to redirect
    standard output/error when using Open/Save/Browse dialogs within widgets.

    Parameters
    ----------
    redirect: bool
        Start redirect (True) or stop redirect (False).
    """
    def __init__(self,
                 name=None,
                 plugin=None,
                 parent=None,
                 options=DEFAULT_OPTIONS):
        super().__init__(name, plugin, parent, options)

        # Widgets
        self._stack = PlotsStackedWidget(parent=self)
        self._shellwidgets = {}
        self.zoom_disp = QSpinBox(self)
        self._right_clicked_thumbnail = None

        # Widget setup
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)

        # Layout
        layout = QHBoxLayout()
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._stack)
        self.setLayout(layout)

        # Signals
        self._stack.sig_figure_loaded.connect(self.sig_figure_loaded)
        self._stack.sig_figure_menu_requested.connect(self.show_figure_menu)
        self._stack.sig_thumbnail_menu_requested.connect(
            self.show_thumbnail_menu)
        self._stack.sig_zoom_changed.connect(self.zoom_disp.setValue)
        self._stack.sig_figure_loaded.connect(self.update_actions)
        self._stack.sig_save_dir_changed.connect(
            lambda val: self.set_option('save_dir', val))

    # --- PluginMainWidget API
    # ------------------------------------------------------------------------
    def get_title(self):
        return _('Plots')

    def get_focus_widget(self):
        widget = self.current_widget()
        if widget and widget.thumbnails_sb.current_thumbnail is not None:
            if widget.figviewer.figcanvas.fig:
                widget = widget.thumbnails_sb.scrollarea

        return widget

    def setup(self, options):
        # Menu actions
        self.mute_action = self.create_action(
            name=PlotsWidgetActions.ToggleMuteInlinePlotting,
            text=_("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda val: self.set_option('mute_inline_plotting', val),
            initial=options['mute_inline_plotting'],
        )
        self.outline_action = self.create_action(
            name=PlotsWidgetActions.ToggleShowPlotOutline,
            text=_("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=lambda val: self.set_option('show_plot_outline', val),
            initial=options['show_plot_outline'],
        )
        self.fit_action = self.create_action(
            name=PlotsWidgetActions.ToggleAutoFitPlotting,
            text=_("Fit plots to window"),
            tip=_("Automatically fit plots to Plot pane size."),
            toggled=lambda val: self.set_option('auto_fit_plotting', val),
            initial=options['auto_fit_plotting'],
        )

        # Toolbar actions
        save_action = self.create_action(
            name=PlotsWidgetActions.Save,
            text=_("Save plot as..."),
            icon=self.create_icon('filesave'),
            triggered=self.save_plot,
            register_shortcut=True,
        )
        save_all_action = self.create_action(
            name=PlotsWidgetActions.SaveAll,
            text=_("Save all plots..."),
            icon=self.create_icon('save_all'),
            triggered=self.save_all_plots,
            register_shortcut=True,
        )
        copy_action = self.create_action(
            name=PlotsWidgetActions.Copy,
            text=_("Copy Image"),
            icon=self.create_icon('editcopy'),
            triggered=self.copy_image,
            register_shortcut=True,
        )
        remove_action = self.create_action(
            name=PlotsWidgetActions.Close,
            text=_("Remove plot"),
            icon=self.create_icon('editclear'),
            triggered=self.remove_plot,
        )
        remove_all_action = self.create_action(
            name=PlotsWidgetActions.CloseAll,
            text=_("Remove all plots"),
            tip=_("Remove all plots"),
            icon=self.create_icon('filecloseall'),
            triggered=self.remove_all_plots,
            register_shortcut=True,
        )
        previous_action = self.create_action(
            name=PlotsWidgetActions.MoveToPreviousFigure,
            text=_("Previous plot"),
            tip=_("Previous plot"),
            icon=self.create_icon('ArrowBack'),
            triggered=self.previous_plot,
            register_shortcut=True,
        )
        next_action = self.create_action(
            name=PlotsWidgetActions.MoveToNextFigure,
            text=_("Next plot"),
            tip=_("Next plot"),
            icon=self.create_icon('ArrowForward'),
            triggered=self.next_plot,
            register_shortcut=True,
        )
        zoom_in_action = self.create_action(
            name=PlotsWidgetActions.ZoomIn,
            text=_("Zoom in"),
            tip=_("Zoom in"),
            icon=self.create_icon('zoom_in'),
            triggered=self.zoom_in,
            register_shortcut=True,
        )
        zoom_out_action = self.create_action(
            name=PlotsWidgetActions.ZoomOut,
            text=_("Zoom out"),
            tip=_("Zoom out"),
            icon=self.create_icon('zoom_out'),
            triggered=self.zoom_out,
            register_shortcut=True,
        )

        # Options menu
        options_menu = self.get_options_menu()
        self.add_item_to_menu(self.mute_action, menu=options_menu)
        self.add_item_to_menu(self.outline_action, menu=options_menu)
        self.add_item_to_menu(self.fit_action, menu=options_menu)

        # Main toolbar
        main_toolbar = self.get_main_toolbar()
        for item in [
                save_action, save_all_action, copy_action, remove_action,
                remove_all_action, previous_action, next_action,
                zoom_in_action, zoom_out_action, self.zoom_disp
        ]:
            self.add_item_to_toolbar(
                item,
                toolbar=main_toolbar,
                section=PlotsWidgetMainToolBarSections.Edit,
            )

        # Context menu
        context_menu = self.create_menu(PluginMainWidgetMenus.Context)
        for item in [save_action, copy_action, remove_action]:
            self.add_item_to_menu(item, menu=context_menu)

    def update_actions(self):
        value = False
        widget = self.current_widget()
        figviewer = None
        if widget:
            figviewer = widget.figviewer
            thumbnails_sb = widget.thumbnails_sb
            value = figviewer.figcanvas.fig is not None

        for __, action in self.get_actions().items():
            if action and action not in [
                    self.mute_action, self.outline_action, self.fit_action
            ]:
                action.setEnabled(value)

                # IMPORTANT: Since we are defining the main actions in here
                # and the context is WidgetWithChildrenShortcut we need to
                # assign the same actions to the children widgets in order
                # for shortcuts to work
                if figviewer:
                    figviewer_actions = figviewer.actions()
                    thumbnails_sb_actions = thumbnails_sb.actions()

                    if action not in figviewer_actions:
                        figviewer.addAction(action)

                    if action not in thumbnails_sb_actions:
                        thumbnails_sb.addAction(action)

        self.zoom_disp.setEnabled(value)

        # Disable zoom buttons if autofit
        if value:
            value = not self.get_option('auto_fit_plotting')
            self.get_action(PlotsWidgetActions.ZoomIn).setEnabled(value)
            self.get_action(PlotsWidgetActions.ZoomOut).setEnabled(value)
            self.zoom_disp.setEnabled(value)

    def on_option_update(self, option, value):
        for index in range(self.count()):
            widget = self._stack.widget(index)
            if widget:
                widget.setup({option: value})
                self.update_actions()

    # --- Public API:
    # ------------------------------------------------------------------------
    def set_current_widget(self, fig_browser):
        """
        Set the current figure browser widget in the stack.

        Parameters
        ----------
        fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser
            The widget to set.
        """
        self._stack.setCurrentWidget(fig_browser)

    def current_widget(self):
        """
        Return the current figure browser widget in the stack.

        Returns
        -------
        spyder.plugins.plots.widgets.figurebrowser.FigureBrowser
            The current widget.
        """
        return self._stack.currentWidget()

    def count(self):
        """
        Return the number of widgets in the stack.

        Returns
        -------
        int
            The number of widgets in the stack.
        """
        return self._stack.count()

    def remove_widget(self, fig_browser):
        """
        Remove widget from stack.

        Parameters
        ----------
        fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser
            The figure browser widget to remove.
        """
        self._stack.removeWidget(fig_browser)

    def add_widget(self, fig_browser):
        """
        Add widget to stack.

        Parameters
        ----------
        fig_browser: spyder.plugins.plots.widgets.figurebrowser.FigureBrowser
            The figure browser widget to add.
        """
        self._stack.addWidget(fig_browser)

    def add_shellwidget(self, shellwidget):
        """
        Add a new shellwidget registered with the plots plugin.

        This function registers a new FigureBrowser for browsing the figures
        in the shell.

        Parameters
        ----------
        shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget
            The shell widget.
        """
        shellwidget_id = id(shellwidget)
        if shellwidget_id not in self._shellwidgets:
            fig_browser = FigureBrowser(parent=self._stack,
                                        background_color=MAIN_BG_COLOR)
            fig_browser.set_shellwidget(shellwidget)
            fig_browser.sig_redirect_stdio_requested.connect(
                self.sig_redirect_stdio_requested)
            self.add_widget(fig_browser)
            self._shellwidgets[shellwidget_id] = fig_browser
            self.set_shellwidget(shellwidget)
            return fig_browser

    def remove_shellwidget(self, shellwidget):
        """
        Remove the shellwidget registered with the plots plugin.

        Parameters
        ----------
        shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget
            The shell widget.
        """
        shellwidget_id = id(shellwidget)
        if shellwidget_id in self._shellwidgets:
            fig_browser = self._shellwidgets.pop(shellwidget_id)
            self.remove_widget(fig_browser)
            fig_browser.close()

    def set_shellwidget(self, shellwidget):
        """
        Update the current shellwidget displayed with the plots plugin.

        Parameters
        ----------
        shelwidget: spyder.plugins.ipyconsole.widgets.shell.ShellWidget
            The shell widget.
        """
        shellwidget_id = id(shellwidget)
        if shellwidget_id in self._shellwidgets:
            fig_browser = self._shellwidgets[shellwidget_id]
            fig_browser.setup(self._options)
            self.set_current_widget(fig_browser)

    def show_figure_menu(self, qpoint):
        """
        Show main figure menu and display on given `qpoint`.

        Parameters
        ----------
        qpoint: QPoint
            The point to display the menu in global coordinated.
        """
        self._right_clicked_thumbnail = None
        widget = self.current_widget()
        if widget:
            self.get_menu(PluginMainWidgetMenus.Context).popup(qpoint)

    def show_thumbnail_menu(self, qpoint, thumbnail):
        """
        Show menu on a given `thumbnail` and display on given `qpoint`.

        Parameters
        ----------
        qpoint: QPoint
            The point to display the menu in global coordinated.
        """
        self._right_clicked_thumbnail = thumbnail
        widget = self.current_widget()
        if widget:
            self.get_menu(PluginMainWidgetMenus.Context).popup(qpoint)

    def save_plot(self):
        """
        Save currently active plot or plot selected to be saved with
        context menu in the thumbnails scrollbar.
        """
        widget = self.current_widget()
        if widget:
            if self._right_clicked_thumbnail is None:
                widget.thumbnails_sb.save_current_figure_as()
            else:
                widget.thumbnails_sb.save_thumbnail_figure_as(
                    self._right_clicked_thumbnail)
                # Reset the toolbar buttons to use the figviewer and not the thumbnail
                # selection
                self._right_clicked_thumbnail = None

    def save_all_plots(self):
        """Save all available plots."""
        widget = self.current_widget()
        if widget:
            widget.thumbnails_sb.save_all_figures_as()

    def copy_image(self):
        """
        Copy currently active plot or plot selected to be copied with
        context menu in the thumbnails scrollbar into the clipboard.
        """
        widget = self.current_widget()
        if widget and widget.figviewer and widget.figviewer.figcanvas.fig:
            if self._right_clicked_thumbnail is None:
                widget.figviewer.figcanvas.copy_figure()
            else:
                self._right_clicked_thumbnail.canvas.copy_figure()
                # Reset the toolbar buttons to use the figviewer and not the thumbnail
                # selection
                self._right_clicked_thumbnail = None

    def remove_plot(self):
        """
        Remove currently active plot or plot selected to be removed with
        context menu in the thumbnails scrollbar.
        """
        widget = self.current_widget()
        if widget:
            if self._right_clicked_thumbnail is None:
                widget.thumbnails_sb.remove_current_thumbnail()
            else:
                widget.thumbnails_sb.remove_thumbnail(
                    self._right_clicked_thumbnail)
                # Reset the toolbar buttons to use the figviewer and not the thumbnail
                # selection
                self._right_clicked_thumbnail = None

        self.update_actions()

    def remove_all_plots(self):
        """Remove all available plots.."""
        widget = self.current_widget()
        if widget:
            widget.thumbnails_sb.remove_all_thumbnails()

        self.update_actions()

    def previous_plot(self):
        """Select the previous plot in the thumbnails scrollbar."""
        widget = self.current_widget()
        if widget:
            widget.thumbnails_sb.go_previous_thumbnail()

    def next_plot(self):
        """Select the next plot in the thumbnails scrollbar."""
        widget = self.current_widget()
        if widget:
            widget.thumbnails_sb.go_next_thumbnail()

    def zoom_in(self):
        """Perform a zoom in on the main figure."""
        widget = self.current_widget()
        if widget:
            widget.zoom_in()

    def zoom_out(self):
        """Perform a zoom out on the main figure."""
        widget = self.current_widget()
        if widget:
            widget.zoom_out()
コード例 #7
0
class ShearMomentTorqueWindow(PyDialog):
    """
    +-------------------------+
    | ShearMomentTorqueWindow |
    +-------------------------+
    | Origin      cid  x y z  |
    | P2          cid  x y z  |
    | z-axis      cid  x y z  |
    | tol         cid  x y z  |
    |                         |
    |    Apply OK Cancel      |
    +-------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

        self._default_font_size = data['font_size']

        #self.dim_max = data['dim_max']
        self.model_name = data['model_name']
        self.cids = data['cids']
        self.gpforce = data['gpforce']
        #self._origin = data['origin']
        #self._p1 = data['origin']
        #self._p2 = data['origin']

        #self.out_data = data

        self.plane_color_float, self.plane_color_int = _check_color(
            data['plane_color'])
        self.plane_opacity = data['plane_opacity']
        self.methods = ['Z-Axis Projection', 'CORD2R']
        self.zaxis_methods = ['Global Z', 'Camera Normal', 'Manual']
        self._zaxis_method = 0  # Global Z

        self.setWindowTitle('Shear, Moment, Torque')
        self.create_widgets()
        self.create_layout()
        self.set_connections()
        self.on_font(self._default_font_size)
        #self.on_gradient_scale()
        #self.show()

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

    def set_font_size(self, font_size):
        """
        Updates the font size of all objects in the PyDialog

        Parameters
        ----------
        font_size : int
            the font size
        """
        if self.font_size == font_size:
            return
        self.font_size = font_size
        font = make_font(font_size, is_bold=False)
        self.setFont(font)
        self.set_bold_font(font_size)

    def set_bold_font(self, font_size):
        """
        Updates the font size of all bolded objects in the dialog

        Parameters
        ----------
        font_size : int
            the font size
        """
        bold_font = make_font(font_size, is_bold=True)

        self.additional_params_label.setFont(bold_font)
        self.case_info_label.setFont(bold_font)
        self.plane_label.setFont(bold_font)

        self.location_label.setFont(bold_font)
        self.cid_label.setFont(bold_font)
        self.x_label.setFont(bold_font)
        self.y_label.setFont(bold_font)
        self.z_label.setFont(bold_font)

    def create_widgets(self):
        """creates the display window"""

        # CORD2R
        #self.origin_label = QLabel("Origin:")
        #self.zaxis_label = QLabel("Z Axis:")
        #self.xz_plane_label = QLabel("XZ Plane:")

        # Z-Axis Projection
        self.p1_label = QLabel("Origin:")
        self.p3_label = QLabel("End:")
        self.p2_label = QLabel("XZ Plane:")
        self.zaxis_label = QLabel("Z Axis:")

        self.method_pulldown = QComboBox()
        for method in self.methods:
            self.method_pulldown.addItem(method)

        self.zaxis_method_pulldown = QComboBox()
        for method in self.zaxis_methods:
            self.zaxis_method_pulldown.addItem(method)

        self.cid_label = QLabel("Coordinate System:")
        self.p1_cid_pulldown = QComboBox()
        self.p2_cid_pulldown = QComboBox()
        self.p3_cid_pulldown = QComboBox()
        self.zaxis_cid_pulldown = QComboBox()

        cid_global_str = '0/Global'
        for cid in sorted(self.cids):
            if cid == 0:
                cid_str = cid_global_str
            else:
                cid_str = str(cid)
            #print('cid_str = %r' % cid_str)
            self.p1_cid_pulldown.addItem(cid_str)
            self.p2_cid_pulldown.addItem(cid_str)
            self.p3_cid_pulldown.addItem(cid_str)
            self.zaxis_cid_pulldown.addItem(cid_str)

        self.p1_cid_pulldown.setCurrentIndex(0)
        self.p2_cid_pulldown.setCurrentIndex(0)
        self.p3_cid_pulldown.setCurrentIndex(0)
        self.zaxis_cid_pulldown.setCurrentIndex(0)
        if len(self.cids) == 1:
            self.p1_cid_pulldown.setEnabled(False)
            self.p2_cid_pulldown.setEnabled(False)
            self.p3_cid_pulldown.setEnabled(False)
            self.zaxis_cid_pulldown.setEnabled(False)

        #self.p1_cid_pulldown.setItemText(0, cid_str)
        #self.p2_cid_pulldown.setItemText(0, cid_str)
        #self.zaxis_cid_pulldown.setItemText(0, cid_str)

        self.p1_cid_pulldown.setToolTip(
            'Defines the coordinate system for Point P1')
        self.p2_cid_pulldown.setToolTip(
            'Defines the coordinate system for Point P2')
        self.p3_cid_pulldown.setToolTip(
            'Defines the coordinate system for Point P3')
        self.zaxis_cid_pulldown.setToolTip(
            'Defines the coordinate system for the Z Axis')

        self.p1_x_edit = QLineEdit('')
        self.p1_y_edit = QLineEdit('')
        self.p1_z_edit = QLineEdit('')

        self.p2_x_edit = QLineEdit('')
        self.p2_y_edit = QLineEdit('')
        self.p2_z_edit = QLineEdit('')

        self.p3_x_edit = QLineEdit('')
        self.p3_y_edit = QLineEdit('')
        self.p3_z_edit = QLineEdit('')

        self.zaxis_x_edit = QLineEdit('')
        self.zaxis_y_edit = QLineEdit('')
        self.zaxis_z_edit = QLineEdit('')

        self.additional_params_label = QLabel('Plane Parameters:')
        self.case_info_label = QLabel('Case Info:')

        self.p2_label = QLabel("XZ Plane:")

        # Plane Color
        self.plane_color_label = QLabel("Plane Color:")
        self.plane_color_edit = QPushButtonColor(self.plane_color_int)

        self.plane_opacity_label = QLabel("Plane Opacity:")
        self.plane_opacity_edit = QDoubleSpinBox()
        self.plane_opacity_edit.setRange(0.1, 1.0)
        self.plane_opacity_edit.setDecimals(1)
        self.plane_opacity_edit.setSingleStep(0.1)
        self.plane_opacity_edit.setValue(self.plane_opacity)

        self.flip_coord_label = QLabel("Flip Coordinate System:")
        self.flip_coord_checkbox = QCheckBox()

        #-----------------------------------------------------------------------
        self.time_label = QLabel('Time:')
        if self.gpforce is None:
            times = ['0.', '0.5', '1.', '1.5', '2.']
            time = '0.'
        else:
            times = [str(time) for time in self.gpforce._times]
            time = times[0]
        self.times_pulldown = make_combo_box(times, time)
        self.time_label.setEnabled(False)
        self.times_pulldown.setEnabled(False)

        #self.node_label = QLabel('Nodes:')
        #self.node_edit = QNodeEdit(self.win_parent, self.model_name, parent=self.gui,
        #pick_style='area', tab_to_next=False)

        #self.element_label = QLabel('Elements:')
        #self.element_edit = QElementEdit(self.win_parent, self.model_name, parent=self.gui,
        #pick_style='area', tab_to_next=False)

        #self.node_element_label = QLabel('Nodes/Elements:')
        #self.node_element_edit = QLineEdit()
        #self.node_element_edit.setReadOnly(True)

        self.nplanes_label = QLabel('Num Planes:')
        self.nplanes_spinner = QSpinBox()
        self.nplanes_spinner.setMinimum(2)
        self.nplanes_spinner.setMaximum(500)
        self.nplanes_spinner.setValue(20)

        #-----------------------------------------------------------------------
        self.method_label = QLabel('Method:')
        self.plane_label = QLabel('Plane:')
        self.location_label = QLabel('Location:')
        self.zaxis_method_label = QLabel('Z-Axis Method:')
        self.cid_label = QLabel('Coordinate System:')
        self.x_label = QLabel('X')
        self.y_label = QLabel('Y')
        self.z_label = QLabel('Z')

        #self.location_label.setAlignment(Qt.AlignCenter)
        self.cid_label.setAlignment(Qt.AlignCenter)

        self.x_label.setAlignment(Qt.AlignCenter)
        self.y_label.setAlignment(Qt.AlignCenter)
        self.z_label.setAlignment(Qt.AlignCenter)

        self.export_checkbox = QCheckBox()
        self.csv_label = QLabel('CSV Filename:')
        self.csv_edit = QLineEdit()
        self.csv_button = QPushButton('Browse...')
        self.csv_label.setEnabled(False)
        self.csv_edit.setEnabled(False)
        self.csv_button.setEnabled(False)
        #-----------------------------------------------------------------------
        # nodes
        self.add_button = QPushButton('Add')
        self.remove_button = QPushButton('Remove')

        # elements
        self.add2_button = QPushButton('Add')
        self.remove2_button = QPushButton('Remove')
        #-----------------------------------------------------------------------
        # closing
        self.apply_button = QPushButton('Apply')
        self.cancel_button = QPushButton('Cancel')
        self.set_bold_font(self._default_font_size)

    @property
    def gui(self):
        if self.win_parent is None:
            return None
        return self.win_parent.parent.gui

    def create_layout(self):
        """sets up the window"""
        grid = self._make_grid_layout()

        #hbox_csv = QHBoxLayout()
        grid2 = QGridLayout()
        irow = 0

        #grid2.addWidget(self.node_label, irow, 0)
        #grid2.addWidget(self.node_edit, irow, 1)
        #grid2.addWidget(self.add_button, irow, 2)
        #grid2.addWidget(self.remove_button, irow, 3)
        #irow += 1

        #grid2.addWidget(self.element_label, irow, 0)
        #grid2.addWidget(self.element_edit, irow, 1)
        #grid2.addWidget(self.add2_button, irow, 2)
        #grid2.addWidget(self.remove2_button, irow, 3)
        #irow += 1

        #grid2.addWidget(self.node_element_label, irow, 0)
        #grid2.addWidget(self.node_element_edit, irow, 1)
        #irow += 1

        hbox_csv = QHBoxLayout()
        hbox_csv.addWidget(self.export_checkbox)
        hbox_csv.addWidget(self.csv_label)
        hbox_csv.addWidget(self.csv_edit)
        hbox_csv.addWidget(self.csv_button)
        #----------------------------------------------

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

        vbox = QVBoxLayout()

        vbox.addLayout(grid)
        vbox.addLayout(grid2)
        #vbox.addStretch()
        vbox.addLayout(hbox_csv)
        vbox.addStretch()

        #-----------------------
        #vbox.addLayout(add_remove_box)
        vbox.addLayout(ok_cancel_box)
        self.on_method(0)
        self.on_zaxis_method(0)
        self.setLayout(vbox)

    def on_export_checkbox(self):
        """this is called when the checkbox is clicked"""
        is_checked = self.export_checkbox.isChecked()
        self.csv_label.setEnabled(is_checked)
        self.csv_edit.setEnabled(is_checked)
        self.csv_button.setEnabled(is_checked)

    def on_browse_csv(self):
        """opens a file dialog"""
        default_dirname = os.getcwd()
        csv_filename, wildcard = save_file_dialog(
            self, 'Select the file name for export', default_dirname,
            wildcard_csv)
        if not csv_filename:
            return
        self.csv_edit.setText(csv_filename)

    def _make_grid_layout(self):
        """builds the QGridLayout"""
        grid = QGridLayout()
        irow = 0
        #-------------------------
        grid.addWidget(self.location_label, irow, 0)
        grid.addWidget(self.cid_label, irow, 1)
        grid.addWidget(self.x_label, irow, 2)
        grid.addWidget(self.y_label, irow, 3)
        grid.addWidget(self.z_label, irow, 4)
        irow += 1

        add_row(irow, grid, self.p1_label, self.p1_cid_pulldown,
                self.p1_x_edit, self.p1_y_edit, self.p1_z_edit)
        irow += 1

        add_row(irow, grid, self.p3_label, self.p3_cid_pulldown,
                self.p3_x_edit, self.p3_y_edit, self.p3_z_edit)
        irow += 1

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

        grid.addWidget(self.method_label, irow, 0)
        grid.addWidget(self.method_pulldown, irow, 1)
        irow += 1

        grid.addWidget(self.zaxis_method_label, irow, 0)
        grid.addWidget(self.zaxis_method_pulldown, irow, 1)
        irow += 1

        add_row(irow, grid, self.zaxis_label, self.zaxis_cid_pulldown,
                self.zaxis_x_edit, self.zaxis_y_edit, self.zaxis_z_edit)
        irow += 1

        add_row(irow, grid, self.p2_label, self.p2_cid_pulldown,
                self.p2_x_edit, self.p2_y_edit, self.p2_z_edit)
        irow += 1

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

        grid.addWidget(self.time_label, irow, 0)
        grid.addWidget(self.times_pulldown, irow, 1)
        irow += 1

        grid.addWidget(self.nplanes_label, irow, 0)
        grid.addWidget(self.nplanes_spinner, irow, 1)
        irow += 1

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

        grid.addWidget(self.plane_color_label, irow, 0)
        grid.addWidget(self.plane_color_edit, irow, 1)
        irow += 1

        grid.addWidget(self.plane_opacity_label, irow, 0)
        grid.addWidget(self.plane_opacity_edit, irow, 1)
        irow += 1
        #----------------------------------------------
        return grid

    def set_connections(self):
        """creates the actions for the menu"""
        self.method_pulldown.currentIndexChanged.connect(self.on_method)
        self.zaxis_method_pulldown.currentIndexChanged.connect(
            self.on_zaxis_method)
        self.plane_color_edit.clicked.connect(self.on_plane_color)

        self.export_checkbox.clicked.connect(self.on_export_checkbox)
        self.csv_button.clicked.connect(self.on_browse_csv)

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

    def on_method(self, method_int=None):
        method = get_pulldown_text(method_int, self.methods,
                                   self.method_pulldown)
        if method == 'Z-Axis Projection':
            is_cord2r = False
        elif method == 'CORD2R':
            is_cord2r = True
        else:
            raise NotImplementedError(method)

        if is_cord2r:
            self._zaxis_method = self.zaxis_method_pulldown.currentIndex()
            # set to manual
            #self.on_zaxis_method(method_int=2)  # manual

            self.zaxis_method_pulldown.setCurrentIndex(2)
            self.on_zaxis_method()  # update
        else:
            self.zaxis_method_pulldown.setCurrentIndex(self._zaxis_method)
            self.on_zaxis_method()  # update

        # works
        self.zaxis_method_pulldown.setEnabled(not is_cord2r)
        self.zaxis_method_pulldown.setVisible(not is_cord2r)
        self.zaxis_method_label.setEnabled(not is_cord2r)

    def on_zaxis_method(self, method_int=None):
        method = get_pulldown_text(method_int, self.zaxis_methods,
                                   self.zaxis_method_pulldown)

        if method == 'Global Z':
            is_visible = False
        elif method == 'Camera Normal':
            is_visible = False
        elif method == 'Manual':
            is_visible = True
        else:
            raise NotImplementedError(method)

        self.zaxis_cid_pulldown.setVisible(is_visible)
        self.zaxis_x_edit.setVisible(is_visible)
        self.zaxis_y_edit.setVisible(is_visible)
        self.zaxis_z_edit.setVisible(is_visible)

    def on_plane_color(self):
        """ Choose a plane color"""
        title = "Choose a cutting plane color"
        rgb_color_ints = self.plane_color_int
        color_edit = self.plane_color_edit
        func_name = 'set_plane_color'
        passed, rgb_color_ints, rgb_color_floats = self._background_color(
            title, color_edit, rgb_color_ints, func_name)
        if passed:
            self.plane_color_int = rgb_color_ints
            self.plane_color_float = rgb_color_floats

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

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

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

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

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

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

    def on_validate(self):
        p1_cidi = self.p1_cid_pulldown.currentText()
        p2_cidi = self.p2_cid_pulldown.currentText()
        p3_cidi = self.p3_cid_pulldown.currentText()
        zaxis_cidi = self.zaxis_cid_pulldown.currentText()
        p1_cid = int(p1_cidi) if 'Global' not in p1_cidi else 0
        p2_cid = int(p2_cidi) if 'Global' not in p2_cidi else 0
        p3_cid = int(p3_cidi) if 'Global' not in p3_cidi else 0
        zaxis_cid = int(zaxis_cidi) if 'Global' not in zaxis_cidi else 0
        #print('p1_cidi=%r p2_cidi=%r p3_cidi=%r' % (p1_cidi, p2_cidi, zaxis_cidi))
        #print('p2_cid=%r p2_cid=%r p3_cidi=%r' % (p2_cid, p2_cid, zaxis_cid))

        p1_x, flag1 = check_float(self.p1_x_edit)
        p1_y, flag2 = check_float(self.p1_y_edit)
        p1_z, flag3 = check_float(self.p1_z_edit)

        p2_x, flag4 = check_float(self.p2_x_edit)
        p2_y, flag5 = check_float(self.p2_y_edit)
        p2_z, flag6 = check_float(self.p2_z_edit)

        p3_x, flag7 = check_float(self.p3_x_edit)
        p3_y, flag8 = check_float(self.p3_y_edit)
        p3_z, flag9 = check_float(self.p3_z_edit)
        p1 = [p1_x, p1_y, p1_z]
        p2 = [p2_x, p2_y, p2_z]
        p3 = [p3_x, p3_y, p3_z]

        flag10, flag11, flag12, zaxis_cid, zaxis = get_zaxis(
            self.win_parent,  # for camera
            self.zaxis_method_pulldown,
            self.zaxis_x_edit,
            self.zaxis_y_edit,
            self.zaxis_z_edit)

        method = self.method_pulldown.currentText()
        assert method in self.methods, 'method=%r' % method
        flag13 = True

        plane_opacity = self.plane_opacity_edit.value()
        nplanes = self.nplanes_spinner.value()

        csv_filename = None
        flag14 = True
        if self.export_checkbox.isChecked():
            csv_filename, flag14 = check_save_path(self.csv_edit)

        flags = [
            flag1, flag2, flag3, flag4, flag5, flag6, flag7, flag8, flag9,
            flag10, flag11, flag12, flag13, flag14
        ]
        if all(flags):
            self.out_data['method'] = method
            self.out_data['p1'] = [p1_cid, p1]
            self.out_data['p2'] = [p2_cid, p2]
            self.out_data['p3'] = [p2_cid, p3]
            self.out_data['zaxis'] = [zaxis_cid, zaxis]
            self.out_data['plane_color'] = self.plane_color_float
            self.out_data['plane_opacity'] = plane_opacity
            self.out_data['nplanes'] = nplanes
            self.out_data['csv_filename'] = csv_filename
            self.out_data['clicked_ok'] = True
            return True
        return False

    def on_apply(self):
        passed = self.on_validate()
        if passed and self.win_parent is not None:
            self.win_parent.shear_moment_torque_obj.make_smt_from_data(
                self.out_data, show=True)
            #self.win_parent.make_smt_from_data(self.out_data)
        return passed

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
コード例 #8
0
class QtLabelsProperties(QtLayerProperties):
    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)

    def changeColor(self):
        self.layer.new_colormap()

    def changeSelection(self, value):
        self.layer.selected_label = value

    def changeSize(self, value):
        self.layer.brush_size = value

    def change_contig(self, state):
        if state == Qt.Checked:
            self.layer.contiguous = True
        else:
            self.layer.contiguous = False

    def change_ndim(self, state):
        if state == Qt.Checked:
            self.layer.n_dimensional = True
        else:
            self.layer.n_dimensional = False

    def _on_colormap_change(self, event):
        self.layer._node.cmap = self.layer.colormap

    def _on_selection_change(self, event):
        with self.layer.events.selected_label.blocker():
            value = self.layer.selected_label
            self.selection_spinbox.setValue(int(value))

    def _on_brush_size_change(self, event):
        with self.layer.events.brush_size.blocker():
            value = self.layer.brush_size
            value = np.clip(int(value), 1, 40)
            self.brush_size_slider.setValue(value)

    def _on_n_dim_change(self, event):
        with self.layer.events.n_dimensional.blocker():
            self.ndim_checkbox.setChecked(self.layer.n_dimensional)

    def _on_contig_change(self, event):
        with self.layer.events.contiguous.blocker():
            self.contig_checkbox.setChecked(self.layer.contiguous)
コード例 #9
0
class FigureBrowser(QWidget):
    """
    Widget to browse the figures that were sent by the kernel to the IPython
    console to be plotted inline.
    """
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()

    def __init__(self,
                 parent=None,
                 options_button=None,
                 plugin_actions=[],
                 background_color=None):
        super(FigureBrowser, self).__init__(parent)

        self.shellwidget = None
        self.is_visible = True
        self.figviewer = None
        self.setup_in_progress = False
        self.background_color = background_color

        # Options :
        self.mute_inline_plotting = None
        self.show_plot_outline = None
        self.auto_fit_plotting = None

        # Option actions :
        self.mute_inline_action = None
        self.show_plot_outline_action = None
        self.auto_fit_action = None

        self.options_button = options_button
        self.plugin_actions = plugin_actions
        self.shortcuts = self.create_shortcuts()

    def eventFilter(self, obj, event):
        """
        An event filter to add the shortcut associated with a given
        toolbutton to its tooltip.
        """
        if event.type() == QEvent.ToolTip:
            add_shortcut_to_tooltip(obj, *obj.shortcut_data)
        return False

    def setup(self,
              mute_inline_plotting=None,
              show_plot_outline=None,
              auto_fit_plotting=None):
        """Setup the figure browser with provided settings."""
        assert self.shellwidget is not None

        self.mute_inline_plotting = mute_inline_plotting
        self.show_plot_outline = show_plot_outline
        self.auto_fit_plotting = auto_fit_plotting

        if self.figviewer is not None:
            self.mute_inline_action.setChecked(mute_inline_plotting)
            self.show_plot_outline_action.setChecked(show_plot_outline)
            self.auto_fit_action.setChecked(auto_fit_plotting)
            return

        # Setup the figure viewer.
        self.figviewer = FigureViewer(background_color=self.background_color)
        self.figviewer.figcanvas.sig_save_fig_requested.connect(
            self.save_figure)
        self.figviewer.figcanvas.sig_clear_fig_requested.connect(
            self.close_figure)

        # Setup the thumbnail scrollbar.
        self.thumbnails_sb = ThumbnailScrollBar(
            self.figviewer, background_color=self.background_color)

        toolbar = self.setup_toolbar()
        self.setup_option_actions(mute_inline_plotting, show_plot_outline,
                                  auto_fit_plotting)

        # Create the layout.
        main_widget = QSplitter()
        main_widget.addWidget(self.figviewer)
        main_widget.addWidget(self.thumbnails_sb)
        main_widget.setFrameStyle(QScrollArea().frameStyle())

        self.tools_layout = QHBoxLayout()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        layout = create_plugin_layout(self.tools_layout, main_widget)
        self.setLayout(layout)

    def setup_toolbar(self):
        """Setup the toolbar."""
        self.savefig_btn = create_toolbutton(self,
                                             icon=ima.icon('filesave'),
                                             tip=_("Save plot as..."),
                                             triggered=self.save_figure)
        self.savefig_btn.shortcut_data = ('plots', 'save')
        self.savefig_btn.installEventFilter(self)

        saveall_btn = create_toolbutton(self,
                                        icon=ima.icon('save_all'),
                                        tip=_("Save all plots..."),
                                        triggered=self.save_all_figures)
        saveall_btn.shortcut_data = ('plots', 'save all')
        saveall_btn.installEventFilter(self)

        copyfig_btn = create_toolbutton(
            self,
            icon=ima.icon('editcopy'),
            tip=_("Copy plot to clipboard as image"),
            triggered=self.copy_figure)
        copyfig_btn.shortcut_data = ('plots', 'copy')
        copyfig_btn.installEventFilter(self)

        self.closefig_btn = create_toolbutton(self,
                                              icon=ima.icon('editclear'),
                                              tip=_("Remove plot"),
                                              triggered=self.close_figure)
        self.closefig_btn.shortcut_data = ('plots', 'close')
        self.closefig_btn.installEventFilter(self)

        closeall_btn = create_toolbutton(self,
                                         icon=ima.icon('filecloseall'),
                                         tip=_("Remove all plots"),
                                         triggered=self.close_all_figures)
        closeall_btn.shortcut_data = ('plots', 'close all')
        closeall_btn.installEventFilter(self)

        separator1 = QFrame()
        separator1.setFrameStyle(QFrame.VLine | QFrame.Sunken)

        goback_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowBack'),
                                       tip=_("Previous plot"),
                                       triggered=self.go_previous_thumbnail)
        goback_btn.shortcut_data = ('plots', 'previous figure')
        goback_btn.installEventFilter(self)

        gonext_btn = create_toolbutton(self,
                                       icon=ima.icon('ArrowForward'),
                                       tip=_("Next plot"),
                                       triggered=self.go_next_thumbnail)
        gonext_btn.shortcut_data = ('plots', 'next figure')
        gonext_btn.installEventFilter(self)

        separator2 = QFrame()
        separator2.setFrameStyle(QFrame.VLine | QFrame.Sunken)

        self.zoom_out_btn = create_toolbutton(self,
                                              icon=ima.icon('zoom_out'),
                                              tip=_("Zoom out"),
                                              triggered=self.zoom_out)
        self.zoom_out_btn.shortcut_data = ('plots', 'zoom out')
        self.zoom_out_btn.installEventFilter(self)

        self.zoom_in_btn = create_toolbutton(self,
                                             icon=ima.icon('zoom_in'),
                                             tip=_("Zoom in"),
                                             triggered=self.zoom_in)
        self.zoom_in_btn.shortcut_data = ('plots', 'zoom in')
        self.zoom_in_btn.installEventFilter(self)

        self.zoom_disp = QSpinBox()
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.zoom_out_btn)
        layout.addWidget(self.zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [
            self.savefig_btn, saveall_btn, copyfig_btn, self.closefig_btn,
            closeall_btn, separator1, goback_btn, gonext_btn, separator2,
            zoom_pan
        ]

    def setup_option_actions(self, mute_inline_plotting, show_plot_outline,
                             auto_fit_plotting):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True
        self.mute_inline_action = create_action(
            self,
            _("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda state: self.option_changed('mute_inline_plotting',
                                                      state))
        self.mute_inline_action.setChecked(mute_inline_plotting)

        self.show_plot_outline_action = create_action(
            self,
            _("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=self.show_fig_outline_in_viewer)
        self.show_plot_outline_action.setChecked(show_plot_outline)

        self.auto_fit_action = create_action(
            self,
            _("Fit plots to window"),
            tip=_("Automatically fit plots to Plot pane size."),
            toggled=self.change_auto_fit_plotting)
        self.auto_fit_action.setChecked(auto_fit_plotting)

        self.actions = [
            self.mute_inline_action, self.show_plot_outline_action,
            self.auto_fit_action
        ]

        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            # When the FigureBowser widget is instatiated outside of the
            # plugin (for testing purpose for instance), we need to create
            # the options_button and set its menu.
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(self.tools_layout.count() - 1,
                                           self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def create_shortcuts(self):
        """Create shortcuts for this widget."""
        copyfig_sc = CONF.config_shortcut(self.copy_figure,
                                          context='plots',
                                          name='copy',
                                          parent=self)

        prevfig = CONF.config_shortcut(self.go_previous_thumbnail,
                                       context='plots',
                                       name='previous figure',
                                       parent=self)

        nextfig = CONF.config_shortcut(self.go_next_thumbnail,
                                       context='plots',
                                       name='next figure',
                                       parent=self)

        savefig_sc = CONF.config_shortcut(self.save_figure,
                                          context='plots',
                                          name='save',
                                          parent=self)

        saveallfig = CONF.config_shortcut(self.save_all_figures,
                                          context='plots',
                                          name='save all',
                                          parent=self)

        closefig = CONF.config_shortcut(self.close_figure,
                                        context='plots',
                                        name='close',
                                        parent=self)

        closeallfig = CONF.config_shortcut(self.close_all_figures,
                                           context='plots',
                                           name='close all',
                                           parent=self)

        zoom_out = CONF.config_shortcut(self.zoom_out,
                                        context='plots',
                                        name='zoom out',
                                        parent=self)

        zoom_in = CONF.config_shortcut(self.zoom_in,
                                       context='plots',
                                       name='zoom in',
                                       parent=self)

        return [
            copyfig_sc, prevfig, nextfig, savefig_sc, saveallfig, closefig,
            closeallfig, zoom_out, zoom_in
        ]

    def get_shortcut_data(self):
        """
        Return shortcut data, a list of tuples (shortcut, text, default).

        shortcut (QShortcut or QAction instance)
        text (string): action/shortcut description
        default (string): default key sequence
        """
        return [sc.data for sc in self.shortcuts]

    def option_changed(self, option, value):
        """Handle when the value of an option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        if self.setup_in_progress is False:
            self.sig_option_changed.emit(option, value)

    def show_fig_outline_in_viewer(self, state):
        """Draw a frame around the figure viewer if state is True."""
        if state is True:
            if is_dark_interface():
                self.figviewer.figcanvas.setStyleSheet(
                    "FigureCanvas{border:1px solid %s;}" %
                    qdarkstyle.palette.DarkPalette.COLOR_BACKGROUND_NORMAL)
            else:
                self.figviewer.figcanvas.setStyleSheet(
                    "FigureCanvas{border: 1px solid %s;}" %
                    self.figviewer.figcanvas.palette().shadow().color().name())
        else:
            self.figviewer.figcanvas.setStyleSheet(
                "FigureCanvas{border: 0px;}")
        self.option_changed('show_plot_outline', state)

    def change_auto_fit_plotting(self, state):
        """Change the auto_fit_plotting option and scale images."""
        self.option_changed('auto_fit_plotting', state)
        self.figviewer.auto_fit_plotting = state
        self.zoom_out_btn.setEnabled(not state)
        self.zoom_in_btn.setEnabled(not state)

    def set_shellwidget(self, shellwidget):
        """Bind the shellwidget instance to the figure browser"""
        self.shellwidget = shellwidget
        shellwidget.set_figurebrowser(self)
        shellwidget.sig_new_inline_figure.connect(self._handle_new_figure)

    def get_actions(self):
        """Get the actions of the widget."""
        return self.actions

    def _handle_new_figure(self, fig, fmt):
        """
        Handle when a new figure is sent to the IPython console by the
        kernel.
        """
        self.thumbnails_sb.add_thumbnail(fig, fmt)

    # ---- Toolbar Handlers
    def zoom_in(self):
        """Zoom the figure in by a single step in the figure viewer."""
        self.figviewer.zoom_in()

    def zoom_out(self):
        """Zoom the figure out by a single step in the figure viewer."""
        self.figviewer.zoom_out()

    def go_previous_thumbnail(self):
        """
        Select the thumbnail previous to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_previous_thumbnail()

    def go_next_thumbnail(self):
        """
        Select the thumbnail next to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_next_thumbnail()

    def save_figure(self):
        """Save the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.save_current_figure_as()

    def save_all_figures(self):
        """Save all the figures in a selected directory."""
        return self.thumbnails_sb.save_all_figures_as()

    def close_figure(self):
        """Close the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_current_thumbnail()

    def close_all_figures(self):
        """Close all the figures in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_all_thumbnails()

    def copy_figure(self):
        """Copy figure from figviewer to clipboard."""
        if self.figviewer and self.figviewer.figcanvas.fig:
            self.figviewer.figcanvas.copy_figure()
コード例 #10
0
ファイル: properties.py プロジェクト: freeman-lab/napari
class QtVectorsLayer(QtLayer):
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.averaging.connect(self._on_avg_change)
        self.layer.events.width.connect(self._on_width_change)
        self.layer.events.length.connect(self._on_len_change)

        # vector color adjustment and widget
        face_comboBox = QComboBox()
        colors = self.layer._colors
        for c in colors:
            face_comboBox.addItem(c)
        index = face_comboBox.findText(self.layer.color, Qt.MatchFixedString)
        if index >= 0:
            face_comboBox.setCurrentIndex(index)
        face_comboBox.activated[str].connect(
            lambda text=face_comboBox: self.change_face_color(text))
        self.grid_layout.addWidget(QLabel('color:'), 3, 0)
        self.grid_layout.addWidget(face_comboBox, 3, 1)

        # line width in pixels
        self.width_field = QDoubleSpinBox()
        self.width_field.setSingleStep(0.1)
        self.width_field.setMinimum(0.1)
        value = self.layer.width
        self.width_field.setValue(value)
        self.width_field.valueChanged.connect(self.change_width)
        self.grid_layout.addWidget(QLabel('width:'), 4, 0)
        self.grid_layout.addWidget(self.width_field, 4, 1)

        # averaging spinbox
        self.averaging_spinbox = QSpinBox()
        self.averaging_spinbox.setSingleStep(1)
        self.averaging_spinbox.setValue(1)
        self.averaging_spinbox.setMinimum(1)
        self.averaging_spinbox.valueChanged.connect(self.change_average_type)
        self.grid_layout.addWidget(QLabel('avg kernel'), 5, 0)
        self.grid_layout.addWidget(self.averaging_spinbox, 5, 1)

        # line length
        self.length_field = QDoubleSpinBox()
        self.length_field.setSingleStep(0.1)
        value = self.layer.length
        self.length_field.setValue(value)
        self.length_field.setMinimum(0.1)
        self.length_field.valueChanged.connect(self.change_length)
        self.grid_layout.addWidget(QLabel('length:'), 6, 0)
        self.grid_layout.addWidget(self.length_field, 6, 1)

        self.setExpanded(False)

    def change_face_color(self, text):
        self.layer.color = text

    def change_connector_type(self, text):
        self.layer.connector = text

    def change_average_type(self, value):
        self.layer.averaging = value

    def change_width(self, value):
        self.layer.width = value

    def change_length(self, value):
        self.layer.length = value

    def _on_avg_change(self, event):
        with self.layer.events.averaging.blocker():
            self.averaging_spinbox.setValue(self.layer.averaging)

    def _on_len_change(self, event):
        with self.layer.events.length.blocker():
            self.length_field.setValue(self.layer.length)

    def _on_width_change(self, event):
        with self.layer.events.width.blocker():
            self.width_field.setValue(self.layer.width)
コード例 #11
0
ファイル: runicadialog.py プロジェクト: shellyWJQ/mnelab
class RunICADialog(QDialog):
    def __init__(self, parent, nchan, methods):
        super().__init__(parent)
        self.setWindowTitle("Run ICA")

        vbox = QVBoxLayout(self)
        grid = QGridLayout()
        grid.addWidget(QLabel("Method:"), 0, 0)
        self.method = QComboBox()
        self.method.addItems(methods)
        self.method.setCurrentIndex(0)
        self.method.currentIndexChanged.connect(self.toggle_options)
        grid.addWidget(self.method, 0, 1)

        self.extended_label = QLabel("Extended:")
        grid.addWidget(self.extended_label, 1, 0)
        self.extended = QCheckBox()
        self.extended.setChecked(True)
        grid.addWidget(self.extended, 1, 1)

        self.ortho_label = QLabel("Orthogonal:")
        grid.addWidget(self.ortho_label, 2, 0)
        self.ortho = QCheckBox()
        self.ortho.setChecked(False)
        grid.addWidget(self.ortho, 2, 1)
        if "Picard" not in methods:
            self.ortho_label.hide()
            self.ortho.hide()

        grid.addWidget(QLabel("Number of components:"), 3, 0)
        self.n_components = QSpinBox()
        self.n_components.setRange(0, nchan)
        self.n_components.setValue(nchan)
        self.n_components.setAlignment(Qt.AlignRight)
        grid.addWidget(self.n_components, 3, 1)

        grid.addWidget(QLabel("Exclude bad segments:"), 4, 0)
        self.exclude_bad_segments = QCheckBox()
        self.exclude_bad_segments.setChecked(True)
        grid.addWidget(self.exclude_bad_segments, 4, 1)

        vbox.addLayout(grid)

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

        self.toggle_options()

    @Slot()
    def toggle_options(self):
        """Toggle extended options."""
        if self.method.currentText() == "Picard":  # enable extended and ortho
            self.extended_label.setEnabled(True)
            self.extended.setEnabled(True)
            self.ortho_label.setEnabled(True)
            self.ortho.setEnabled(True)
        elif self.method.currentText() == "Infomax":  # enable extended
            self.extended_label.setEnabled(True)
            self.extended.setEnabled(True)
            self.ortho_label.setEnabled(False)
            self.ortho.setChecked(False)
            self.ortho.setEnabled(False)
        else:
            self.extended_label.setEnabled(False)
            self.extended.setChecked(False)
            self.extended.setEnabled(False)
            self.ortho_label.setEnabled(False)
            self.ortho.setChecked(False)
            self.ortho.setEnabled(False)
コード例 #12
0
ファイル: preferences.py プロジェクト: mtnakayama/pyNastran
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Show corner coord
        self.corner_coord_label = QLabel("Show Corner Coordinate System:")
        self.corner_coord_checkbox = QCheckBox()
        self.corner_coord_checkbox.setChecked(self._show_corner_coord)

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

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

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

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

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

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

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

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

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

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

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

    def create_layout(self):
        grid = QGridLayout()

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

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

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

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

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

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

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

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

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

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

        grid.addWidget(self.corner_coord_label, irow, 0)
        grid.addWidget(self.corner_coord_checkbox, irow, 1)
        irow += 1

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_corner_coord(self):
        is_checked = self.corner_coord_checkbox.isChecked()
        if self.win_parent is not None:
            self.win_parent.set_corner_axis_visiblity(is_checked, render=True)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
コード例 #13
0
ファイル: itemproperties.py プロジェクト: MrLeeh/jsonwatchqt
class ItemPropertyDialog(QDialog):
    def __init__(self, jsonitem: JsonItem, parent=None):
        super().__init__(parent)

        assert jsonitem is not None
        self.item = jsonitem

        # name
        self.nameLabel = QLabel(self.tr("name:"))
        self.nameLineEdit = QLineEdit(self.item.name or "")
        self.nameLabel.setBuddy(self.nameLineEdit)

        # unit
        self.unitLabel = QLabel(self.tr("unit:"))
        self.unitLineEdit = QLineEdit(self.item.unit or "")
        self.unitLabel.setBuddy(self.unitLineEdit)

        # type
        self.typeLabel = QLabel(self.tr("type:"))
        self.typeComboBox = QComboBox()
        self.typeComboBox.addItems([k for k, t in VALUETYPES])
        self.typeComboBox.setCurrentIndex(
            self.typeComboBox.findText(self.item.type))
        self.typeComboBox.currentIndexChanged.connect(self.data_changed)
        self.typeLabel.setBuddy(self.typeComboBox)

        # decimals
        self.decimalsLabel = QLabel(self.tr("decimals:"))
        self.decimalsSpinBox = QSpinBox()
        self.decimalsSpinBox.setRange(0, 10)
        self.decimalsSpinBox.setValue(self.item.decimals or 0)
        self.decimalsLabel.setBuddy(self.decimalsSpinBox)
        self.decimalsSpinBox.valueChanged.connect(self.data_changed)
        self.last_decimals = self.decimalsSpinBox.value()

        # min
        self.minLabel = QLabel(self.tr("minimum:"))
        self.minSpinBox =QDoubleSpinBox()
        self.minSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.minLabel.setBuddy(self.minSpinBox)
        self.minSpinBox.setValue(self.item.min or 0.0)

        # max
        self.maxLabel = QLabel(self.tr("maximum:"))
        self.maxSpinBox = QDoubleSpinBox()
        self.maxSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.maxSpinBox.setValue(self.item.max or 100.0)

        # numerator
        self.scalefactorLabel = QLabel(self.tr("scalefactor:"))
        self.scalefactorSpinBox = NoZerosDoubleSpinBox()
        self.scalefactorSpinBox.setRange(-sys.maxsize, sys.maxsize)
        self.scalefactorSpinBox.setButtonSymbols(QSpinBox.NoButtons)
        self.scalefactorSpinBox.setDecimals(10)
        self.scalefactorSpinBox.setValue(self.item.scalefactor or 1)
        self.scalefactorLabel.setBuddy(self.scalefactorSpinBox)

        # readonly
        self.readonlyCheckBox = QCheckBox(self.tr("readonly"))
        self.readonlyCheckBox.setChecked(Qt.Checked if self.item.readonly
                                         else Qt.Unchecked)
        self.readonlyCheckBox.stateChanged.connect(self.data_changed)

        # buttons
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel,
            Qt.Horizontal
        )
        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

        # layout
        layout = QGridLayout()
        layout.addWidget(self.nameLabel, 0, 0)
        layout.addWidget(self.nameLineEdit, 0, 1)
        layout.addWidget(self.unitLabel, 1, 0)
        layout.addWidget(self.unitLineEdit, 1, 1)
        layout.addWidget(self.typeLabel, 2, 0)
        layout.addWidget(self.typeComboBox, 2, 1)
        layout.addWidget(self.decimalsLabel, 3, 0)
        layout.addWidget(self.decimalsSpinBox, 3, 1)
        layout.addWidget(self.minLabel, 4, 0)
        layout.addWidget(self.minSpinBox, 4, 1)
        layout.addWidget(self.maxLabel, 5, 0)
        layout.addWidget(self.maxSpinBox, 5, 1)
        layout.addWidget(self.scalefactorLabel, 6, 0)
        layout.addWidget(self.scalefactorSpinBox, 6, 1)
        layout.addWidget(self.readonlyCheckBox, 7, 0, 1, 2)
        layout.addWidget(self.buttons, 8, 0, 1, 2)
        self.setLayout(layout)

        # misc
        self.setWindowTitle("Edit JsonItem '%s'" % self.item.key)
        self.data_changed()

    def accept(self):
        self.item.name = self.nameLineEdit.text()
        self.item.unit = self.unitLineEdit.text()
        self.item.decimals = self.decimalsSpinBox.value()
        self.item.min = self.minSpinBox.value()
        self.item.max = self.maxSpinBox.value()
        self.item.scalefactor = self.scalefactorSpinBox.value()
        self.item.readonly = self.readonlyCheckBox.checkState() == Qt.Checked
        self.item.type = self.typeComboBox.currentText()
        return super().accept()

    def data_changed(self):
        type_numeric = self.typeComboBox.currentText() not in ('bool', 'str')
        type_int = self.typeComboBox.currentText() == 'int'
        readonly  = self.readonlyCheckBox.checkState() == Qt.Checked

        # not used properties invisible
        self.decimalsSpinBox.setVisible(type_numeric)
        self.decimalsLabel.setVisible(type_numeric)

        self.scalefactorSpinBox.setVisible(type_numeric)
        self.scalefactorLabel.setVisible(type_numeric)

        self.minSpinBox.setVisible(type_numeric and not readonly)
        self.minLabel.setVisible(type_numeric and not readonly)

        self.maxSpinBox.setVisible(type_numeric and not readonly)
        self.maxLabel.setVisible(type_numeric and not readonly)

        self.unitLineEdit.setVisible(type_numeric)
        self.unitLabel.setVisible(type_numeric)

        # no decimals for int
        self.minSpinBox.setDecimals(self.decimalsSpinBox.value())
        self.maxSpinBox.setDecimals(self.decimalsSpinBox.value())

        if type_int:
            delta = self.decimalsSpinBox.value() - self.last_decimals
            self.scalefactorSpinBox.setValue(
                self.scalefactorSpinBox.value() / 10**delta
            )

        self.last_decimals = self.decimalsSpinBox.value()
コード例 #14
0
class ImageRotationDialog(ExToolWindow):
    def __init__(self, signal, axes, parent, plugin):
        super(ImageRotationDialog, self).__init__(parent)
        self.ui = parent
        self.create_controls()
        self.accepted.connect(self.ok)
        self.rejected.connect(self.close_new)
        self.signal = signal
        self.plugin = plugin
        self.new_out = None
        self._connected_updates = False
        if isinstance(axes, str):
            axm = signal.signal.axes_manager
            if axes.startswith("nav"):
                axes = (axm._axes.index(axm.navigation_axes[0]),
                        axm._axes.index(axm.navigation_axes[1]))
            elif axes.startswith("sig"):
                axes = (axm._axes.index(axm.signal_axes[0]),
                        axm._axes.index(axm.signal_axes[1]))
        self.axes = axes
        self.setWindowTitle(tr("Rotate"))

        # TODO: TAG: Functionality check
        if not hasattr(signal.signal, 'events'):
            self.gbo_preview.setVisible(False)

        # TODO: Add dynamic rotation, e.g. one that rotates when source
        # signal's data_changed event triggers

    def connect(self):
        # TODO: Don't have to con/dis those in gbo
        self.opt_new.toggled.connect(self.close_new)
        self.num_angle.valueChanged.connect(self.update)
        self.chk_grid.toggled.connect(self.update)
        self.num_grid.valueChanged.connect(self.update)
        self.chk_reshape.toggled.connect(self.update)
        self.opt_new.toggled.connect(self.update)
        self.opt_replace.toggled.connect(self.update)

    def disconnect(self):
        self.num_angle.valueChanged.disconnect(self.update)
        self.chk_grid.toggled.disconnect(self.update)
        self.num_grid.valueChanged.disconnect(self.update)
        self.chk_reshape.toggled.disconnect(self.update)
        self.opt_new.toggled.disconnect(self.update)
        self.opt_replace.toggled.disconnect(self.update)

    def ok(self):
        # Draw figure if not already done
        # TODO: TAG: Functionality check
        if not hasattr(self.signal.signal, 'events') or \
                not self.gbo_preview.isChecked():
            self.update()
        angle = self.num_angle.value()
        reshape = self.chk_reshape.isChecked()
        self.plugin.record_code(
            r"<p>.rotate_signal({0}, reshape={1}, axes={2})".format(
                angle, reshape, self.axes))
        # Clean up event connections
        if self.new_out is not None:
            self.connect_update_plot(self.new_out.signal, disconnect=True)

    def close_new(self, value=False):
        if self.new_out is not None and not value:
            self.new_out.close()
            self.new_out = None
            self._connected_updates = False

    def set_preview(self, value):
        if not hasattr(self.signal.signal, 'events'):
            return
        if value:
            self.connect()
            self.update()
        else:
            self.disconnect()
            self.close_new()

    def _axes_in_nav(self):
        axm = self.signal.signal.axes_manager
        navidx = [axm._axes.index(ax) for ax in axm.navigation_axes]
        if self.axes[0] in navidx:
            return True
        return False

    def connect_update_plot(self, signal, disconnect=False):
        if self._connected_updates != disconnect:
            return  # Nothing to do, prevent double connections
        if self._axes_in_nav():
            f = signal._plot.navigator_plot.update
        else:
            f = signal._plot.signal_plot.update

        # TODO: TAG: Functionality check
        if hasattr(signal, 'events') and hasattr(signal.events,
                                                 'data_changed'):
            if disconnect:
                signal.events.data_changed.disconnect(f)
            else:
                signal.events.data_changed.connect(f, [])
        self._connected_updates = not disconnect

    def update(self):
        angle = self.num_angle.value()
        reshape = self.chk_reshape.isChecked()
        if self.opt_new.isChecked():
            if self.new_out is None:
                out = None
            else:
                out = self.new_out.signal
        elif self.opt_replace.isChecked():
            out = self.signal.signal
        else:
            return  # Indeterminate state, do nothing

        s = self.plugin.rotate_signal(angle,
                                      self.signal.signal,
                                      record=False,
                                      reshape=reshape,
                                      out=out,
                                      axes=self.axes)

        if out is None:
            s.metadata.General.title = self.signal.name + "[Rotated]"
            s.plot()
            self.connect_update_plot(s)
            if (self.gbo_preview.isChecked() and self.opt_new.isChecked()
                    and self.new_out is None):
                self.new_out = self.ui.lut_signalwrapper[s]
        else:
            s = out

        if self.chk_grid.isChecked() is True:
            pass  # TODO: Draw grid

    def create_controls(self):
        """
        Create UI controls.
        """
        vbox = QVBoxLayout()

        form = QFormLayout()
        self.num_angle = QDoubleSpinBox()
        self.num_angle.setValue(0.0)
        self.num_angle.setMinimum(-360)
        self.num_angle.setMaximum(360)
        form.addRow(tr("Angle:"), self.num_angle)
        vbox.addLayout(form)

        self.gbo_preview = QGroupBox(tr("Preview"))
        self.gbo_preview.setCheckable(True)
        self.gbo_preview.setChecked(False)
        gbo_vbox = QVBoxLayout()
        self.chk_grid = QCheckBox(tr("Grid"))
        self.chk_grid.setChecked(False)
        self.num_grid = QSpinBox()
        self.num_grid.setValue(4)
        self.num_grid.setMinimum(1)
        self.num_grid.setEnabled(False)
        self.chk_grid.toggled[bool].connect(self.num_grid.setEnabled)
        gbo_vbox.addWidget(self.chk_grid)
        gbo_vbox.addWidget(self.num_grid)
        self.gbo_preview.setLayout(gbo_vbox)
        vbox.addWidget(self.gbo_preview)

        self.gbo_preview.toggled[bool].connect(self.set_preview)

        self.gbo_output = QGroupBox(tr("Output"))
        self.opt_new = QRadioButton(tr("New signal"))
        self.opt_replace = QRadioButton(tr("In place"))
        self.opt_new.setChecked(True)
        gbo_vbox2 = QVBoxLayout()
        gbo_vbox2.addWidget(self.opt_new)
        gbo_vbox2.addWidget(self.opt_replace)
        self.gbo_output.setLayout(gbo_vbox2)
        vbox.addWidget(self.gbo_output)

        self.chk_reshape = QCheckBox(tr("Resize to fit"))
        self.chk_reshape.setChecked(False)
        vbox.addWidget(self.chk_reshape)

        self.btn_ok = QPushButton(tr("&OK"))
        self.btn_ok.setDefault(True)
        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel = QPushButton(tr("&Cancel"))
        self.btn_cancel.clicked.connect(self.reject)
        hbox = QHBoxLayout()
        hbox.addWidget(self.btn_ok)
        hbox.addWidget(self.btn_cancel)
        vbox.addLayout(hbox)

        vbox.addStretch(1)
        self.setLayout(vbox)
コード例 #15
0
class DimensionMDE(Dimension):
    binningChanged = Signal()
    """
    MDEventWorkspace has additional properties for either number_of_bins or thickness

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

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

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

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

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

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

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

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

    def set_state(self, state):
        super().set_state(state)
        if self.state == State.X:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.Y:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.NONE:
            self.spinBins.hide()
            self.spinThick.show()
            self.rebinLabel.setText('thick')
        else:
            self.spinBins.hide()
            self.spinThick.hide()
            self.rebinLabel.hide()
コード例 #16
0
ファイル: qt_labels_layer.py プロジェクト: xies/napari
class QtLabelsControls(QtLayerControls):
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_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.layer.events.editable.connect(self._on_editable_change)

        # shuffle colormap button
        self.colormapUpdate = QPushButton('shuffle colors')
        self.colormapUpdate.setObjectName('shuffle')
        self.colormapUpdate.clicked.connect(self.changeColor)
        self.colormapUpdate.setFixedHeight(28)

        # selection spinbox
        self.selectionSpinBox = QSpinBox()
        self.selectionSpinBox.setKeyboardTracking(False)
        self.selectionSpinBox.setSingleStep(1)
        self.selectionSpinBox.setMinimum(0)
        self.selectionSpinBox.setMaximum(2147483647)
        self.selectionSpinBox.valueChanged.connect(self.changeSelection)
        self._on_selection_change(None)

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        sld.valueChanged[int].connect(lambda value=sld: self.changeSize(value))
        self.brushSizeSlider = sld
        self._on_brush_size_change(None)

        contig_cb = QCheckBox()
        contig_cb.setToolTip('contiguous editing')
        contig_cb.stateChanged.connect(
            lambda state=contig_cb: self.change_contig(state))
        self.contigCheckBox = contig_cb
        self._on_contig_change(None)

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip('n-dimensional editing')
        ndim_cb.stateChanged.connect(
            lambda state=ndim_cb: self.change_ndim(state))
        self.ndimCheckBox = ndim_cb
        self._on_n_dim_change(None)

        self.panzoom_button = QtModeButton(layer, 'zoom', Mode.PAN_ZOOM,
                                           'Pan/zoom mode')
        self.pick_button = QtModeButton(layer, 'picker', Mode.PICKER,
                                        'Pick mode')
        self.paint_button = QtModeButton(layer, 'paint', Mode.PAINT,
                                         'Paint mode')
        self.fill_button = QtModeButton(layer, 'fill', Mode.FILL, 'Fill mode')

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.paint_button)
        self.button_group.addButton(self.pick_button)
        self.button_group.addButton(self.fill_button)
        self.panzoom_button.setChecked(True)
        self._on_editable_change(None)

        button_row = QHBoxLayout()
        button_row.addWidget(self.pick_button)
        button_row.addWidget(self.fill_button)
        button_row.addWidget(self.paint_button)
        button_row.addWidget(self.panzoom_button)
        button_row.addStretch(1)
        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, 1, 2)
        self.grid_layout.addWidget(self.colormapUpdate, 0, 0)
        self.grid_layout.addWidget(QLabel('label:'), 1, 0)
        self.grid_layout.addWidget(self.selectionSpinBox, 1, 2)
        self.grid_layout.addWidget(QtColorBox(layer), 1, 1)
        self.grid_layout.addWidget(QLabel('opacity:'), 2, 0)
        self.grid_layout.addWidget(self.opacitySilder, 2, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('brush size:'), 3, 0)
        self.grid_layout.addWidget(self.brushSizeSlider, 3, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('blending:'), 4, 0)
        self.grid_layout.addWidget(self.blendComboBox, 4, 1, 1, 2)
        self.grid_layout.addWidget(QLabel('contiguous:'), 5, 0)
        self.grid_layout.addWidget(self.contigCheckBox, 5, 1)
        self.grid_layout.addWidget(QLabel('n-dim:'), 6, 0)
        self.grid_layout.addWidget(self.ndimCheckBox, 6, 1)
        self.grid_layout.setRowStretch(7, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def mouseMoveEvent(self, event):
        self.layer.status = str(self.layer.mode)

    def _on_mode_change(self, event):
        mode = event.mode
        if mode == Mode.PAN_ZOOM:
            self.panzoom_button.setChecked(True)
        elif mode == Mode.PICKER:
            self.pick_button.setChecked(True)
        elif mode == Mode.PAINT:
            self.paint_button.setChecked(True)
        elif mode == Mode.FILL:
            self.fill_button.setChecked(True)
        else:
            raise ValueError("Mode not recongnized")

    def changeColor(self):
        self.layer.new_colormap()

    def changeSelection(self, value):
        self.layer.selected_label = value
        self.selectionSpinBox.clearFocus()
        self.setFocus()

    def changeSize(self, value):
        self.layer.brush_size = value

    def change_contig(self, state):
        if state == Qt.Checked:
            self.layer.contiguous = True
        else:
            self.layer.contiguous = False

    def change_ndim(self, state):
        if state == Qt.Checked:
            self.layer.n_dimensional = True
        else:
            self.layer.n_dimensional = False

    def _on_selection_change(self, event):
        with self.layer.events.selected_label.blocker():
            value = self.layer.selected_label
            self.selectionSpinBox.setValue(int(value))

    def _on_brush_size_change(self, event):
        with self.layer.events.brush_size.blocker():
            value = self.layer.brush_size
            value = np.clip(int(value), 1, 40)
            self.brushSizeSlider.setValue(value)

    def _on_n_dim_change(self, event):
        with self.layer.events.n_dimensional.blocker():
            self.ndimCheckBox.setChecked(self.layer.n_dimensional)

    def _on_contig_change(self, event):
        with self.layer.events.contiguous.blocker():
            self.contigCheckBox.setChecked(self.layer.contiguous)

    def _on_editable_change(self, event):
        self.pick_button.setEnabled(self.layer.editable)
        self.paint_button.setEnabled(self.layer.editable)
        self.fill_button.setEnabled(self.layer.editable)
コード例 #17
0
ファイル: arrayeditor.py プロジェクト: ChunHungLiu/spyder
class ArrayEditor(QDialog):
    """Array Editor Dialog"""    
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        
        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)
        
        self.data = None
        self.arraywidget = None
        self.stack = None
        self.layout = None
        # Values for 3d array editor
        self.dim_indexes = [{}, {}, {}]
        self.last_dim = 0  # Adjust this for changing the startup dimension
        
    def setup_and_check(self, data, title='', readonly=False,
                        xlabels=None, ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)
        if data.size == 0:
            self.error(_("Array is empty"))
            return False
        if data.ndim > 3:
            self.error(_("Arrays with more than 3 dimensions are not supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(_("The 'xlabels' argument length do no match array "
                         "column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(_("The 'ylabels' argument length do no match array row "
                         "number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('str') \
               and not dtn.startswith('unicode'):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False
        
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = to_text_string(title) + " - " + _("NumPy array")
        else:
            title = _("Array editor")
        if readonly:
            title += ' (' + _('read only') + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)
        
        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(ArrayEditorWidget(self, data[name],
                                                   readonly, xlabels, ylabels))
        elif is_masked_array:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly,
                                                   xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.data, readonly,
                                                   xlabels, ylabels))
            self.stack.addWidget(ArrayEditorWidget(self, data.mask, readonly,
                                                   xlabels, ylabels))
        elif data.ndim == 3:
            pass
        else:
            self.stack.addWidget(ArrayEditorWidget(self, data, readonly,
                                                   xlabels, ylabels))
        self.arraywidget = self.stack.currentWidget()
        self.stack.currentChanged.connect(self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array or data.ndim == 3:
            if is_record_array:
                btn_layout.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not is_text_string(title):
                            title = repr(title)
                        text += ' - '+title
                    names.append(text)
            else:
                names = [_('Masked data'), _('Data'), _('Mask')]
            if data.ndim == 3:
                # QSpinBox
                self.index_spin = QSpinBox(self, keyboardTracking=False)
                self.index_spin.valueChanged.connect(self.change_active_widget)
                # QComboBox
                names = [str(i) for i in range(3)]
                ra_combo = QComboBox(self)
                ra_combo.addItems(names)
                ra_combo.currentIndexChanged.connect(self.current_dim_changed)    
                # Adding the widgets to layout
                label = QLabel(_("Axis:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(ra_combo)
                self.shape_label = QLabel()
                btn_layout.addWidget(self.shape_label)
                label = QLabel(_("Index:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(self.index_spin)
                self.slicing_label = QLabel()
                btn_layout.addWidget(self.slicing_label)
                # set the widget to display when launched
                self.current_dim_changed(self.last_dim)
            else:
                ra_combo = QComboBox(self)
                ra_combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
                ra_combo.addItems(names)
                btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel(_("<u>Warning</u>: changes are applied separately"))
                label.setToolTip(_("For performance reasons, changes applied "\
                                   "to masked array won't be reflected in "\
                                   "array's data (and vice-versa)."))
                btn_layout.addWidget(label)
            btn_layout.addStretch()
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)

        self.setMinimumSize(400, 300)
        
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)
        
        return True
            
    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)     
            
    def change_active_widget(self, index):
        """
        This is implemented for handling negative values in index for
        3d arrays, to give the same behavior as slicing
        """
        string_index = [':']*3
        string_index[self.last_dim] = '<font color=red>%i</font>'
        self.slicing_label.setText((r"Slicing: [" + ", ".join(string_index) +
                                "]") % index)
        if index < 0:
            data_index = self.data.shape[self.last_dim] + index
        else:
            data_index = index
        slice_index = [slice(None)]*3
        slice_index[self.last_dim] = data_index

        stack_index = self.dim_indexes[self.last_dim].get(data_index)
        if stack_index == None:
            stack_index = self.stack.count()
            self.stack.addWidget(ArrayEditorWidget(self,
                                                   self.data[slice_index]))
            self.dim_indexes[self.last_dim][data_index] = stack_index
            self.stack.update()
        self.stack.setCurrentIndex(stack_index)

    def current_dim_changed(self, index):
        """
        This change the active axis the array editor is plotting over
        in 3D
        """
        self.last_dim = index
        string_size = ['%i']*3
        string_size[index] = '<font color=red>%i</font>'
        self.shape_label.setText(('Shape: (' + ', '.join(string_size) +
                                 ')    ') % self.data.shape)
        if self.index_spin.value() != 0:
            self.index_spin.setValue(0)
        else:
            # this is done since if the value is currently 0 it does not emit
            # currentIndexChanged(int)
            self.change_active_widget(0)
        self.index_spin.setRange(-self.data.shape[index],
                                 self.data.shape[index]-1)

    @Slot()
    def accept(self):
        """Reimplement Qt method"""
        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()
        QDialog.accept(self)
        
    def get_value(self):
        """Return modified array -- this is *not* a copy"""
        # It is import to avoid accessing Qt C++ object as it has probably
        # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
        return self.data

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, _("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    @Slot()
    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
コード例 #18
0
class DimensionMDE(Dimension):
    binningChanged = Signal()
    """
    MDEventWorkspace has additional properties for either number_of_bins or thickness

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

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

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

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

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

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

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

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

    def set_state(self, state):
        super(DimensionMDE, self).set_state(state)
        if self.state == State.X:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.Y:
            self.spinBins.show()
            self.spinThick.hide()
            self.rebinLabel.setText('bins')
        elif self.state == State.NONE:
            self.spinBins.hide()
            self.spinThick.show()
            self.rebinLabel.setText('thick')
        else:
            self.spinBins.hide()
            self.spinThick.hide()
            self.rebinLabel.hide()
コード例 #19
0
class DimensionNonIntegrated(Dimension):
    binningChanged = Signal()
    """
    A dimension that can either be sliced through or rebinned. It
    has additional properties for either number_of_bins or thickness

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

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

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

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

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

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

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

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

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

        """
        self.value = value
        # temporary disable updating value from slider change
        self.update_value_from_slider = False
        self.update_slider()
        self.update_value_from_slider = True
        self.update_spinbox()
コード例 #20
0
ファイル: confpage.py プロジェクト: asdlei99/spyder
class LSPServerEditor(QDialog):
    DEFAULT_HOST = '127.0.0.1'
    DEFAULT_PORT = 2084
    DEFAULT_CMD = ''
    DEFAULT_ARGS = ''
    DEFAULT_CONFIGURATION = '{}'
    DEFAULT_EXTERNAL = False
    DEFAULT_STDIO = False
    HOST_REGEX = re.compile(r'^\w+([.]\w+)*$')
    NON_EMPTY_REGEX = re.compile(r'^\S+$')
    JSON_VALID = _('Valid JSON')
    JSON_INVALID = _('Invalid JSON')
    MIN_SIZE = QSize(850, 600)
    INVALID_CSS = "QLineEdit {border: 1px solid red;}"
    VALID_CSS = "QLineEdit {border: 1px solid green;}"

    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, stdio=False,
                 configurations={}, **kwargs):
        super(LSPServerEditor, self).__init__(parent)

        description = _(
            "To create a new server configuration, you need to select a "
            "programming language, set the command to start its associated "
            "server and enter any arguments that should be passed to it on "
            "startup. Additionally, you can set the server's hostname and "
            "port if connecting to an external server, "
            "or to a local one using TCP instead of stdio pipes."
            "<br><br>"
            "<i>Note</i>: You can use the placeholders <tt>{host}</tt> and "
            "<tt>{port}</tt> in the server arguments field to automatically "
            "fill in the respective values.<br>"
        )
        self.parent = parent
        self.external = external

        # Widgets
        self.server_settings_description = QLabel(description)
        self.lang_cb = QComboBox(self)
        self.external_cb = QCheckBox(_('External server'), self)
        self.host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.cmd_label = QLabel(_('Command:'))
        self.cmd_input = QLineEdit(self)
        self.args_label = QLabel(_('Arguments:'))
        self.args_input = QLineEdit(self)
        self.json_label = QLabel(self.JSON_VALID, self)
        self.conf_label = QLabel(_('<b>Server Configuration:</b>'))
        self.conf_input = CodeEditor(None)

        self.bbox = QDialogButtonBox(QDialogButtonBox.Ok |
                                     QDialogButtonBox.Cancel)
        self.button_ok = self.bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = self.bbox.button(QDialogButtonBox.Cancel)

        # Widget setup
        self.setMinimumSize(self.MIN_SIZE)
        self.setWindowTitle(_('LSP server editor'))

        self.server_settings_description.setWordWrap(True)

        self.lang_cb.setToolTip(
            _('Programming language provided by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        self.button_ok.setEnabled(False)
        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        self.host_input.setPlaceholderText('127.0.0.1')
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        self.cmd_input.setText(cmd)
        self.cmd_input.setPlaceholderText('/absolute/path/to/command')

        self.args_input.setToolTip(
            _('Additional arguments required to start the server'))
        self.args_input.setText(args)
        self.args_input.setPlaceholderText(r'--host {host} --port {port}')

        self.conf_input.setup_editor(
            language='json',
            color_scheme=CONF.get('appearance', 'selected'),
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json',
            folding=False
        )
        self.conf_input.set_language('json', 'config.json')
        self.conf_input.setToolTip(_('Additional LSP server configuration '
                                     'set at runtime. JSON required'))
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            conf_text = '{}'
        self.conf_input.set_text(conf_text)

        self.external_cb.setToolTip(
            _('Check if the server runs on a remote location'))
        self.external_cb.setChecked(external)

        self.stdio_cb = QCheckBox(_('Use stdio pipes for communication'), self)
        self.stdio_cb.setToolTip(_('Check if the server communicates '
                                   'using stdin/out pipes'))
        self.stdio_cb.setChecked(stdio)

        # Layout setup
        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(self.server_settings_description)

        vlayout = QVBoxLayout()

        lang_group = QGroupBox(_('Language'))
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(self.lang_cb)
        lang_group.setLayout(lang_layout)
        vlayout.addWidget(lang_group)

        server_group = QGroupBox(_('Language server'))
        server_layout = QGridLayout()
        server_layout.addWidget(self.cmd_label, 0, 0)
        server_layout.addWidget(self.cmd_input, 0, 1)
        server_layout.addWidget(self.args_label, 1, 0)
        server_layout.addWidget(self.args_input, 1, 1)
        server_group.setLayout(server_layout)
        vlayout.addWidget(server_group)

        address_group = QGroupBox(_('Server address'))
        host_layout = QVBoxLayout()
        host_layout.addWidget(self.host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(self.port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        address_group.setLayout(conn_info_layout)
        vlayout.addWidget(address_group)

        advanced_group = QGroupBox(_('Advanced'))
        advanced_layout = QVBoxLayout()
        advanced_layout.addWidget(self.external_cb)
        advanced_layout.addWidget(self.stdio_cb)
        advanced_group.setLayout(advanced_layout)
        vlayout.addWidget(advanced_group)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(self.conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        vlayout.addStretch()
        hlayout.addLayout(vlayout, 2)
        hlayout.addLayout(conf_layout, 3)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(self.bbox)
        self.setLayout(general_vlayout)
        self.form_status(False)

        # Signals
        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())
        self.external_cb.stateChanged.connect(self.set_local_options)
        self.stdio_cb.stateChanged.connect(self.set_stdio_options)
        self.lang_cb.currentIndexChanged.connect(self.lang_selection_changed)
        self.conf_input.textChanged.connect(self.validate)
        self.bbox.accepted.connect(self.accept)
        self.bbox.rejected.connect(self.reject)

        # Final setup
        if language is not None:
            self.form_status(True)
            self.validate()
            if stdio:
                self.set_stdio_options(True)
            if external:
                self.set_local_options(True)

    @Slot()
    def validate(self):
        host_text = self.host_input.text()
        cmd_text = self.cmd_input.text()

        if not self.HOST_REGEX.match(host_text):
            self.button_ok.setEnabled(False)
            self.host_input.setStyleSheet(self.INVALID_CSS)
            if bool(host_text):
                self.host_input.setToolTip(_('Hostname must be valid'))
            else:
                self.host_input.setToolTip(
                    _('Hostname or IP address of the host on which the server '
                      'is running. Must be non empty.'))
        else:
            self.host_input.setStyleSheet(self.VALID_CSS)
            self.host_input.setToolTip(_('Hostname is valid'))
            self.button_ok.setEnabled(True)

        if not self.external:
            if not self.NON_EMPTY_REGEX.match(cmd_text):
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(self.INVALID_CSS)
                self.cmd_input.setToolTip(
                    _('Command used to start the LSP server locally. Must be '
                      'non empty'))
                return

            if find_program(cmd_text) is None:
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(self.INVALID_CSS)
                self.cmd_input.setToolTip(_('Program was not found '
                                            'on your system'))
            else:
                self.cmd_input.setStyleSheet(self.VALID_CSS)
                self.cmd_input.setToolTip(_('Program was found on your '
                                            'system'))
                self.button_ok.setEnabled(True)

        try:
            json.loads(self.conf_input.toPlainText())
            try:
                self.json_label.setText(self.JSON_VALID)
            except Exception:
                pass
        except ValueError:
            try:
                self.json_label.setText(self.JSON_INVALID)
                self.button_ok.setEnabled(False)
            except Exception:
                pass

    def form_status(self, status):
        self.host_input.setEnabled(status)
        self.port_spinner.setEnabled(status)
        self.external_cb.setEnabled(status)
        self.stdio_cb.setEnabled(status)
        self.cmd_input.setEnabled(status)
        self.args_input.setEnabled(status)
        self.conf_input.setEnabled(status)
        self.json_label.setVisible(status)

    @Slot()
    def lang_selection_changed(self):
        idx = self.lang_cb.currentIndex()
        if idx == 0:
            self.set_defaults()
            self.form_status(False)
            self.button_ok.setEnabled(False)
        else:
            server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1])
            self.form_status(True)
            if server is not None:
                self.host_input.setText(server.host)
                self.port_spinner.setValue(server.port)
                self.external_cb.setChecked(server.external)
                self.stdio_cb.setChecked(server.stdio)
                self.cmd_input.setText(server.cmd)
                self.args_input.setText(server.args)
                self.conf_input.set_text(json.dumps(server.configurations))
                self.json_label.setText(self.JSON_VALID)
                self.button_ok.setEnabled(True)
            else:
                self.set_defaults()

    def set_defaults(self):
        self.cmd_input.setStyleSheet('')
        self.host_input.setStyleSheet('')
        self.host_input.setText(self.DEFAULT_HOST)
        self.port_spinner.setValue(self.DEFAULT_PORT)
        self.external_cb.setChecked(self.DEFAULT_EXTERNAL)
        self.stdio_cb.setChecked(self.DEFAULT_STDIO)
        self.cmd_input.setText(self.DEFAULT_CMD)
        self.args_input.setText(self.DEFAULT_ARGS)
        self.conf_input.set_text(self.DEFAULT_CONFIGURATION)
        self.json_label.setText(self.JSON_VALID)

    @Slot(bool)
    @Slot(int)
    def set_local_options(self, enabled):
        self.external = enabled
        self.cmd_input.setEnabled(True)
        self.args_input.setEnabled(True)
        if enabled:
            self.cmd_input.setEnabled(False)
            self.cmd_input.setStyleSheet('')
            self.args_input.setEnabled(False)
            self.stdio_cb.stateChanged.disconnect()
            self.stdio_cb.setChecked(False)
            self.stdio_cb.setEnabled(False)
        else:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.stdio_cb.setEnabled(True)
            self.stdio_cb.setChecked(False)
            self.stdio_cb.stateChanged.connect(self.set_stdio_options)
        try:
            self.validate()
        except Exception:
            pass

    @Slot(bool)
    @Slot(int)
    def set_stdio_options(self, enabled):
        self.stdio = enabled
        if enabled:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.external_cb.stateChanged.disconnect()
            self.external_cb.setChecked(False)
            self.external_cb.setEnabled(False)
            self.host_input.setStyleSheet('')
            self.host_input.setEnabled(False)
            self.port_spinner.setEnabled(False)
        else:
            self.cmd_input.setEnabled(True)
            self.args_input.setEnabled(True)
            self.external_cb.setChecked(False)
            self.external_cb.setEnabled(True)
            self.external_cb.stateChanged.connect(self.set_local_options)
            self.host_input.setEnabled(True)
            self.port_spinner.setEnabled(True)
        try:
            self.validate()
        except Exception:
            pass

    def get_options(self):
        language_idx = self.lang_cb.currentIndex()
        language = LSP_LANGUAGES[language_idx - 1]
        host = self.host_input.text()
        port = int(self.port_spinner.value())
        external = self.external_cb.isChecked()
        stdio = self.stdio_cb.isChecked()
        args = self.args_input.text()
        cmd = self.cmd_input.text()
        configurations = json.loads(self.conf_input.toPlainText())
        server = LSPServer(language=language.lower(), cmd=cmd, args=args,
                           host=host, port=port, external=external,
                           stdio=stdio, configurations=configurations)
        return server
コード例 #21
0
ファイル: lspmanager.py プロジェクト: cfanpc/spyder
class LSPServerEditor(QDialog):
    DEFAULT_HOST = '127.0.0.1'
    DEFAULT_PORT = 2084
    DEFAULT_CMD = ''
    DEFAULT_ARGS = ''
    DEFAULT_CONFIGURATION = '{}'
    DEFAULT_EXTERNAL = False
    HOST_REGEX = re.compile(r'^\w+([.]\w+)*$')
    NON_EMPTY_REGEX = re.compile(r'^\S+$')
    JSON_VALID = _('JSON valid')
    JSON_INVALID = _('JSON invalid')

    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>%(host)s</tt> and '
                        '<tt>%(port)s</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(_('Programming language provided '
                                  'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(_('Name of the host that will provide '
                                     'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(_('Command used to start the '
                                    'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(_('Additional arguments required to '
                                     'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('appearance', 'selected')
        self.conf_input.setup_editor(
            language='JSON',
            color_scheme=color_scheme,
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json')
        self.conf_input.setToolTip(_('Additional LSP server configurations '
                                     'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(_('Check if the server runs '
                                      'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(
            self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()

    @Slot()
    def validate(self):
        host_text = self.host_input.text()
        cmd_text = self.cmd_input.text()
        if not self.HOST_REGEX.match(host_text):
            self.button_ok.setEnabled(False)
            self.host_input.setStyleSheet("QLineEdit{border: 1px solid red;}")
            self.host_input.setToolTip('Hostname must be valid')
            return
        else:
            self.host_input.setStyleSheet(
                "QLineEdit{border: 1px solid green;}")
            self.host_input.setToolTip('Hostname is valid')
            self.button_ok.setEnabled(True)

        if not self.external:
            if not self.NON_EMPTY_REGEX.match(cmd_text):
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Command must be non empty')
                return

            if find_program(cmd_text) is None:
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Program was not found '
                                          'on your system')
                return
            else:
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid green;}")
                self.cmd_input.setToolTip('Program was found on your system')
                self.button_ok.setEnabled(True)
        try:
            json.loads(self.conf_input.toPlainText())
            try:
                self.json_label.setText(self.JSON_VALID)
            except:
                pass
        except (ValueError, json.decoder.JSONDecodeError):
            try:
                self.json_label.setText(self.JSON_INVALID)
                self.button_ok.setEnabled(False)
            except:
                pass

    def form_status(self, status):
        self.host_input.setEnabled(status)
        self.port_spinner.setEnabled(status)
        self.external_cb.setEnabled(status)
        self.cmd_input.setEnabled(status)
        self.args_input.setEnabled(status)
        self.conf_input.setEnabled(status)
        self.json_label.setVisible(status)

    @Slot()
    def lang_selection_changed(self):
        idx = self.lang_cb.currentIndex()
        if idx == 0:
            self.set_defaults()
            self.form_status(False)
            self.button_ok.setEnabled(False)
        else:
            server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1])
            self.form_status(True)
            if server is not None:
                self.host_input.setText(server.host)
                self.port_spinner.setValue(server.port)
                self.external_cb.setChecked(server.external)
                self.cmd_input.setText(server.cmd)
                self.args_input.setText(server.args)
                self.conf_input.set_text(json.dumps(server.configurations))
                self.json_label.setText(self.JSON_VALID)
                self.button_ok.setEnabled(True)
            else:
                self.set_defaults()

    def set_defaults(self):
        self.cmd_input.setStyleSheet('')
        self.host_input.setStyleSheet('')
        self.host_input.setText(self.DEFAULT_HOST)
        self.port_spinner.setValue(self.DEFAULT_PORT)
        self.external_cb.setChecked(self.DEFAULT_EXTERNAL)
        self.cmd_input.setText(self.DEFAULT_CMD)
        self.args_input.setText(self.DEFAULT_ARGS)
        self.conf_input.set_text(self.DEFAULT_CONFIGURATION)
        self.json_label.setText(self.JSON_VALID)

    @Slot(bool)
    @Slot(int)
    def set_local_options(self, enabled):
        self.external = enabled
        self.cmd_input.setEnabled(True)
        self.args_input.setEnabled(True)
        if enabled:
            self.cmd_input.setEnabled(False)
            self.cmd_input.setStyleSheet('')
            self.args_input.setEnabled(False)
        try:
            self.validate()
        except:
            pass

    def get_options(self):
        language_idx = self.lang_cb.currentIndex()
        language = LSP_LANGUAGES[language_idx - 1]
        host = self.host_input.text()
        port = int(self.port_spinner.value())
        external = self.external_cb.isChecked()
        args = self.args_input.text()
        cmd = self.cmd_input.text()
        configurations = json.loads(self.conf_input.toPlainText())
        server = LSPServer(language=language.lower(), cmd=cmd, args=args,
                           host=host, port=port, external=external,
                           configurations=configurations)
        return server
コード例 #22
0
class RunICADialog(QDialog):
    def __init__(self, parent, nchan, have_picard=True, have_sklearn=True):
        super().__init__(parent)
        self.setWindowTitle("Run ICA")
        vbox = QVBoxLayout(self)
        grid = QGridLayout()
        grid.addWidget(QLabel("Method:"), 0, 0)
        self.method = QComboBox()
        self.methods = {"Infomax": "infomax"}
        if have_sklearn:
            self.methods["FastICA"] = "fastica"
        if have_picard:
            self.methods["Picard"] = "picard"
        self.method.addItems(self.methods.keys())
        if have_picard:
            self.method.setCurrentText("Picard")
        else:
            self.method.setCurrentText("Infomax")
        min_len = max(len(key) for key in self.methods.keys())
        self.method.setMinimumContentsLength(min_len)
        grid.addWidget(self.method, 0, 1)

        self.extended_label = QLabel("Extended:")
        grid.addWidget(self.extended_label, 1, 0)
        self.extended = QCheckBox()
        self.extended.setChecked(True)
        grid.addWidget(self.extended, 1, 1)

        self.ortho_label = QLabel("Orthogonal:")
        grid.addWidget(self.ortho_label, 2, 0)
        self.ortho = QCheckBox()
        self.ortho.setChecked(False)
        grid.addWidget(self.ortho, 2, 1)

        self.toggle_options()
        self.method.currentIndexChanged.connect(self.toggle_options)

        grid.addWidget(QLabel("Number of components:"), 3, 0)
        self.n_components = QSpinBox()
        self.n_components.setMinimum(0)
        self.n_components.setMaximum(nchan)
        self.n_components.setValue(nchan)
        self.n_components.setAlignment(Qt.AlignRight)
        grid.addWidget(self.n_components, 3, 1)
        grid.addWidget(QLabel("Exclude bad segments:"), 4, 0)
        self.exclude_bad_segments = QCheckBox()
        self.exclude_bad_segments.setChecked(True)
        grid.addWidget(self.exclude_bad_segments)
        vbox.addLayout(grid)
        buttonbox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Cancel)
        vbox.addWidget(buttonbox)
        buttonbox.accepted.connect(self.accept)
        buttonbox.rejected.connect(self.reject)
        vbox.setSizeConstraint(QVBoxLayout.SetFixedSize)

    @Slot()
    def toggle_options(self):
        """Toggle extended options.
        """
        if self.method.currentText() == "Picard":
            self.extended_label.show()
            self.extended.show()
            self.ortho_label.show()
            self.ortho.show()
        elif self.method.currentText() == "Infomax":
            self.extended_label.show()
            self.extended.show()
            self.ortho_label.hide()
            self.ortho.hide()
        else:
            self.extended_label.hide()
            self.extended.hide()
            self.ortho_label.hide()
            self.ortho.hide()
コード例 #23
0
ファイル: power_bcs.py プロジェクト: mtnakayama/pyNastran
class BreakSurfaceMenu(QDialog):
    def __init__(self, data, win_parent=None):
        """
        +-----------------+
        | Break Surfaces  |
        +-----------------+------+
        |  EngineInlet           |
        |  EngineOutlet          |
        |                        |
        |  Name      EngineInlet |
        |  RegionMode * RegionID |
        |             * All      |
        |                        |
        |  AllowedRegions:       |
        |    Region ID      3    |
        |                        |
        |  PickMode  * All       |
        |  Pick Mode  x On/Off   |
        |  Pick Angle   20 deg   |
        |                        |
        |         Revert         |
        |     RenumberRegions    |
        |         Close          |
        +------------------------+
        """
        QDialog.__init__(self, win_parent)
        self.setWindowTitle('Break Surface')

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

        self.points = data['points']

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

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

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

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

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

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

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

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

        self.mode_header = QLabel("Mode:")

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

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

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

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

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

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

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

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

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

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

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

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

        self.close_button = QPushButton("Close")

        self.create_layout()
        #self.set_connections()

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

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

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

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

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

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

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

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

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

        grid1 = QGridLayout()
        grid2 = QGridLayout()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def set_connections(self):
        self.opacity_edit.clicked.connect(self.on_opacity)
        self.point_size.clicked.connect(self.on_point_size)
        self.color_edit.clicked.connect(self.on_color)
        self.checkbox_show.clicked.connect(self.on_show)
        self.checkbox_hide.clicked.connect(self.on_hide)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_close(self):
        self.out_data['clicked_close'] = True
        self.close()
コード例 #24
0
ファイル: preferences.py プロジェクト: RogerTang/pyNastran
class PreferencesWindow(PyDialog):
    """
    +-------------+
    | Preferences |
    +---------------------------------+
    | Text Size        ______ Default |
    | Annotation Color ______         |
    | Annotation Size  ______         |
    | Picker Size      ______         |
    | Back Color       ______         |
    | Text Color       ______         |
    |                                 |
    |        Apply OK Cancel          |
    +---------------------------------+
    """
    def __init__(self, data, win_parent=None):
        """
        Saves the data members from data and
        performs type checks
        """
        PyDialog.__init__(self, data, win_parent)

        self._updated_preference = False

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

        self.dim_max = data['dim_max']
        self._default_annotation_size = data['annotation_size']  # int

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def create_layout(self):
        grid = QGridLayout()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def on_cancel(self):
        self.out_data['close'] = True
        self.close()
コード例 #25
0
class RotateLabelDlg(QDialog):

    rotateSelectedPolygon = QtCore.Signal(bool, int)

    def __init__(self,
                 parent=None,
                 rotation_connection=None,
                 clockwise=True,
                 angle=0):
        super(RotateLabelDlg, self).__init__(parent)
        self.setWindowTitle(self.tr("Rotate the selected polygon"))
        if rotation_connection is not None:
            self.rotateSelectedPolygon.connect(rotation_connection)
        self.clockwise = clockwise
        self.angle = angle
        self.setLayout(self.createLayout())
        self.setFixedSize(400, 80)

    def resetRotateDlg(self, parent_topright):
        self.clockwise = True
        self.angle = 0
        self.radio_clockwise.setChecked(self.clockwise)
        self.angle_editor.setValue(self.angle)
        self.rotate_bar.updateRotationInfo(self.clockwise, self.angle)
        size = self.size()
        self.move(parent_topright.x() - size.width(), parent_topright.y())

    def createLayout(self):
        hbox = QHBoxLayout()
        self.radio_clockwise = QRadioButton(self.tr("clockwise"), self)
        self.radio_clockwise.clockwise = True
        self.radio_clockwise.setChecked(self.clockwise)
        self.radio_clockwise.toggled.connect(self.rotationDirectionChanged)

        self.radio_anticlockwise = QRadioButton(self.tr("anticlockwise"), self)
        self.radio_anticlockwise.clockwise = False
        self.radio_anticlockwise.setChecked(not self.clockwise)
        self.radio_anticlockwise.toggled.connect(self.rotationDirectionChanged)

        self.angle_editor = QSpinBox(self)
        self.angle_editor.setButtonSymbols(
            QtWidgets.QAbstractSpinBox.NoButtons)
        self.angle_editor.setRange(0, 360)
        self.angle_editor.setSuffix(" °")
        self.angle_editor.setValue(self.angle)
        self.angle_editor.setToolTip("rotation angle")
        self.angle_editor.setStatusTip(self.toolTip())
        self.angle_editor.setAlignment(QtCore.Qt.AlignCenter)
        self.angle_editor.valueChanged.connect(self.rotationAngleChanged)

        hbox.addWidget(self.radio_anticlockwise)
        hbox.addWidget(self.radio_clockwise)
        hbox.addWidget(self.angle_editor)

        self.rotate_bar = AngleBar(self, self.clockwise, self.angle,
                                   self.angleBarChanged)

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        vbox.addWidget(self.rotate_bar)
        return vbox

    def rotationDirectionChanged(self, value):
        # radio button
        rbtn = self.sender()
        if rbtn.isChecked():
            self.clockwise = rbtn.clockwise
            self.rotate_bar.updateRotationInfo(self.clockwise, self.angle)
            self.appleRotateInfo()

    def rotationAngleChanged(self, value):
        # spinbox
        if value != self.angle:
            self.angle = value
            self.rotate_bar.updateRotationInfo(self.clockwise, self.angle)
            self.appleRotateInfo()

    def angleBarChanged(self, clockwise, angle):
        if self.clockwise == clockwise and self.angle == angle:
            return
        self.clockwise = clockwise
        self.angle = angle

        self.angle_editor.setValue(self.angle)
        if self.clockwise and not self.radio_clockwise.isChecked():
            self.radio_clockwise.setChecked(True)
        elif not self.clockwise and not self.radio_anticlockwise.isChecked():
            self.radio_anticlockwise.setChecked(True)
        else:
            self.appleRotateInfo()

    def appleRotateInfo(self):
        self.rotateSelectedPolygon.emit(self.clockwise, self.angle)
コード例 #26
0
class NewConfigurationDialog(QDialog):
    """A dialog for selecting defaults for a new configuration."""
    def __init__(self, configuration_path, parent=None):
        QDialog.__init__(self, parent)

        self.setModal(True)
        self.setWindowTitle("New configuration file")
        self.setMinimumWidth(250)
        self.setMinimumHeight(150)

        layout = QFormLayout()

        directory, filename = os.path.split(configuration_path)

        if directory.strip() == "":
            directory = os.path.abspath(os.curdir)
            self.configuration_path = "%s/%s" % (directory, filename)
        else:
            self.configuration_path = configuration_path

        configuration_location = QLabel()
        configuration_location.setText(directory)

        configuration_name = QLabel()
        configuration_name.setText(filename)

        self.num_realizations = QSpinBox()
        self.num_realizations.setMinimum(1)
        self.num_realizations.setMaximum(1000)
        self.num_realizations.setValue(10)

        self.storage_path = QLineEdit()
        self.storage_path.setText("Storage")
        self.storage_path.textChanged.connect(self._validateName)

        layout.addRow(createSpace(10))
        layout.addRow("Configuration name:", configuration_name)
        layout.addRow("Configuration location:", configuration_location)
        layout.addRow("Path to store DBase:", self.storage_path)
        layout.addRow("Number of realizations", self.num_realizations)
        layout.addRow(createSpace(10))

        buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self)
        self.ok_button = buttons.button(QDialogButtonBox.Ok)

        layout.addRow(buttons)

        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        self.setLayout(layout)

    def getNumberOfRealizations(self):
        return self.num_realizations.value()

    def getConfigurationPath(self):
        return self.configuration_path

    def getStoragePath(self):
        """Return the DBase storage path"""
        return str(self.storage_path.text()).strip()

    def _validateName(self, name):
        name = str(name)
        enabled = len(name) > 0 and name.find(" ") == -1
        self.ok_button.setEnabled(enabled)
コード例 #27
0
class QtLabelsControls(QtLayerControls):
    """Qt view and controls for the napari Labels layer.

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

    Attributes
    ----------
    button_group : qtpy.QtWidgets.QButtonGroup
        Button group of labels layer modes: PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    colormapUpdate : qtpy.QtWidgets.QPushButton
        Button to update colormap of label layer.
    contigCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to control if label layer is contiguous.
    fill_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select FILL mode on Labels layer.
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : napari.layers.Labels
        An instance of a napari Labels layer.
    ndimCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to control if label layer is n-dimensional.
    paint_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAINT mode on Labels layer.
    panzoom_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAN_ZOOM mode on Labels layer.
    pick_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PICKER mode on Labels layer.
    erase_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select ERASE mode on Labels layer.
    selectionSpinBox : qtpy.QtWidgets.QSpinBox
        Widget to select a specific label by its index.

    Raises
    ------
    ValueError
        Raise error if label mode is not PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    """
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_change)
        self.layer.events.selected_label.connect(
            self._on_selected_label_change)
        self.layer.events.brush_size.connect(self._on_brush_size_change)
        self.layer.events.contiguous.connect(self._on_contiguous_change)
        self.layer.events.n_dimensional.connect(self._on_n_dimensional_change)
        self.layer.events.contour.connect(self._on_contour_change)
        self.layer.events.editable.connect(self._on_editable_change)
        self.layer.events.preserve_labels.connect(
            self._on_preserve_labels_change)
        self.layer.events.color_mode.connect(self._on_color_mode_change)

        # selection spinbox
        self.selectionSpinBox = QSpinBox()
        self.selectionSpinBox.setKeyboardTracking(False)
        self.selectionSpinBox.setSingleStep(1)
        self.selectionSpinBox.setMinimum(0)
        self.selectionSpinBox.setMaximum(1024)
        self.selectionSpinBox.valueChanged.connect(self.changeSelection)
        self.selectionSpinBox.setAlignment(Qt.AlignCenter)
        self._on_selected_label_change()

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        sld.valueChanged.connect(self.changeSize)
        self.brushSizeSlider = sld
        self._on_brush_size_change()

        contig_cb = QCheckBox()
        contig_cb.setToolTip(trans._('contiguous editing'))
        contig_cb.stateChanged.connect(self.change_contig)
        self.contigCheckBox = contig_cb
        self._on_contiguous_change()

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip(trans._('edit all dimensions'))
        ndim_cb.stateChanged.connect(self.change_ndim)
        self.ndimCheckBox = ndim_cb
        self._on_n_dimensional_change()

        contour_sb = QSpinBox()
        contour_sb.setToolTip(trans._('display contours of labels'))
        contour_sb.valueChanged.connect(self.change_contour)
        self.contourSpinBox = contour_sb
        self.contourSpinBox.setKeyboardTracking(False)
        self.contourSpinBox.setSingleStep(1)
        self.contourSpinBox.setMinimum(0)
        self.contourSpinBox.setMaximum(2147483647)
        self.contourSpinBox.setAlignment(Qt.AlignCenter)
        self._on_contour_change()

        preserve_labels_cb = QCheckBox()
        preserve_labels_cb.setToolTip(
            trans._('preserve existing labels while painting'))
        preserve_labels_cb.stateChanged.connect(self.change_preserve_labels)
        self.preserveLabelsCheckBox = preserve_labels_cb
        self._on_preserve_labels_change()

        selectedColorCheckbox = QCheckBox()
        selectedColorCheckbox.setToolTip(
            trans._("Display only selected label"))
        selectedColorCheckbox.stateChanged.connect(self.toggle_selected_mode)
        self.selectedColorCheckbox = selectedColorCheckbox

        # shuffle colormap button
        self.colormapUpdate = QtModePushButton(
            None,
            'shuffle',
            slot=self.changeColor,
            tooltip=trans._('shuffle colors'),
        )

        self.panzoom_button = QtModeRadioButton(
            layer,
            'zoom',
            Mode.PAN_ZOOM,
            tooltip=trans._('Pan/zoom mode (Space)'),
            checked=True,
        )
        self.pick_button = QtModeRadioButton(layer,
                                             'picker',
                                             Mode.PICK,
                                             tooltip=trans._('Pick mode (L)'))
        self.paint_button = QtModeRadioButton(
            layer, 'paint', Mode.PAINT, tooltip=trans._('Paint mode (P)'))
        self.fill_button = QtModeRadioButton(
            layer,
            'fill',
            Mode.FILL,
            tooltip=trans._("Fill mode (F) \nToggle with {key}".format(
                key=KEY_SYMBOLS['Control'])),
        )
        self.erase_button = QtModeRadioButton(
            layer,
            'erase',
            Mode.ERASE,
            tooltip=trans._("Erase mode (E) \nToggle with {key}".format(
                key=KEY_SYMBOLS['Alt'])),
        )

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.paint_button)
        self.button_group.addButton(self.pick_button)
        self.button_group.addButton(self.fill_button)
        self.button_group.addButton(self.erase_button)
        self._on_editable_change()

        button_row = QHBoxLayout()
        button_row.addStretch(1)
        button_row.addWidget(self.colormapUpdate)
        button_row.addWidget(self.erase_button)
        button_row.addWidget(self.fill_button)
        button_row.addWidget(self.paint_button)
        button_row.addWidget(self.pick_button)
        button_row.addWidget(self.panzoom_button)
        button_row.setSpacing(4)
        button_row.setContentsMargins(0, 0, 0, 5)

        brush_shape_comboBox = QComboBox(self)
        for index, (data,
                    text) in enumerate(LABEL_BRUSH_SHAPE_TRANSLATIONS.items()):
            data = data.value
            brush_shape_comboBox.addItem(text, data)
            if self.layer.brush_shape == data:
                brush_shape_comboBox.setCurrentIndex(index)

        brush_shape_comboBox.activated[str].connect(self.change_brush_shape)
        self.brushShapeComboBox = brush_shape_comboBox
        self._on_brush_shape_change()

        color_mode_comboBox = QComboBox(self)
        for index, (data,
                    text) in enumerate(LABEL_COLOR_MODE_TRANSLATIONS.items()):
            data = data.value
            color_mode_comboBox.addItem(text, data)

            if self.layer.color_mode == data:
                color_mode_comboBox.setCurrentIndex(index)

        color_mode_comboBox.activated[str].connect(self.change_color_mode)
        self.colorModeComboBox = color_mode_comboBox
        self._on_color_mode_change()

        color_layout = QHBoxLayout()
        self.colorBox = QtColorBox(layer)
        color_layout.addWidget(self.colorBox)
        color_layout.addWidget(self.selectionSpinBox)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_row, 0, 0, 1, 4)
        self.grid_layout.addWidget(QLabel(trans._('label:')), 1, 0, 1, 1)
        self.grid_layout.addLayout(color_layout, 1, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('opacity:')), 2, 0, 1, 1)
        self.grid_layout.addWidget(self.opacitySlider, 2, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('brush size:')), 3, 0, 1, 1)
        self.grid_layout.addWidget(self.brushSizeSlider, 3, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('brush shape:')), 4, 0, 1, 1)
        self.grid_layout.addWidget(self.brushShapeComboBox, 4, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('blending:')), 5, 0, 1, 1)
        self.grid_layout.addWidget(self.blendComboBox, 5, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('color mode:')), 6, 0, 1, 1)
        self.grid_layout.addWidget(self.colorModeComboBox, 6, 1, 1, 3)
        self.grid_layout.addWidget(QLabel(trans._('contour:')), 7, 0, 1, 1)
        self.grid_layout.addWidget(self.contourSpinBox, 7, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('contiguous:')), 8, 0, 1, 1)
        self.grid_layout.addWidget(self.contigCheckBox, 8, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('n-dim:')), 8, 2, 1, 1)
        self.grid_layout.addWidget(self.ndimCheckBox, 8, 3, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('preserve labels:')), 9, 0,
                                   1, 2)
        self.grid_layout.addWidget(self.preserveLabelsCheckBox, 9, 1, 1, 1)
        self.grid_layout.addWidget(QLabel(trans._('show selected:')), 9, 2, 1,
                                   1)
        self.grid_layout.addWidget(self.selectedColorCheckbox, 9, 3, 1, 1)
        self.grid_layout.setRowStretch(9, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def _on_mode_change(self, event):
        """Receive layer model mode change event and update checkbox ticks.

        Parameters
        ----------
        event : napari.utils.event.Event
            The napari event that triggered this method.

        Raises
        ------
        ValueError
            Raise error if event.mode is not PAN_ZOOM, PICK, PAINT, ERASE, or
            FILL
        """
        mode = event.mode
        if mode == Mode.PAN_ZOOM:
            self.panzoom_button.setChecked(True)
        elif mode == Mode.PICK:
            self.pick_button.setChecked(True)
        elif mode == Mode.PAINT:
            self.paint_button.setChecked(True)
        elif mode == Mode.FILL:
            self.fill_button.setChecked(True)
        elif mode == Mode.ERASE:
            self.erase_button.setChecked(True)
        else:
            raise ValueError(trans._("Mode not recognized"))

    def changeColor(self):
        """Change colormap of the label layer."""
        self.layer.new_colormap()

    def changeSelection(self, value):
        """Change currently selected label.

        Parameters
        ----------
        value : int
            Index of label to select.
        """
        self.layer.selected_label = value
        self.selectionSpinBox.clearFocus()
        self.setFocus()

    def toggle_selected_mode(self, state):
        if state == Qt.Checked:
            self.layer.show_selected_label = True
        else:
            self.layer.show_selected_label = False

    def changeSize(self, value):
        """Change paint brush size.

        Parameters
        ----------
        value : float
            Size of the paint brush.
        """
        self.layer.brush_size = value

    def change_contig(self, state):
        """Toggle contiguous state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if labels are contiguous.
        """
        if state == Qt.Checked:
            self.layer.contiguous = True
        else:
            self.layer.contiguous = False

    def change_ndim(self, state):
        """Toggle n-dimensional state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if label layer is n-dimensional.
        """
        if state == Qt.Checked:
            self.layer.n_dimensional = True
        else:
            self.layer.n_dimensional = False

    def change_contour(self, value):
        """Change contour thickness.

        Parameters
        ----------
        value : int
            Thickness of contour.
        """
        self.layer.contour = value
        self.contourSpinBox.clearFocus()
        self.setFocus()

    def change_preserve_labels(self, state):
        """Toggle preserve_labels state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if overwriting label is enabled.
        """
        if state == Qt.Checked:
            self.layer.preserve_labels = True
        else:
            self.layer.preserve_labels = False

    def change_color_mode(self, new_mode):
        """Change color mode of label layer.

        Parameters
        ----------
        new_mode : str
            AUTO (default) allows color to be set via a hash function with a seed.
            DIRECT allows color of each label to be set directly by a color dictionary.
        """
        self.layer.color_mode = self.colorModeComboBox.currentData()

    def change_brush_shape(self, brush_shape):
        """Change paintbrush shape of label layer.

        Parameters
        ----------
        brush_shape : str
            CIRCLE (default) uses circle paintbrush (case insensitive).
            SQUARE uses square paintbrush (case insensitive).
        """
        self.layer.brush_shape = self.brushShapeComboBox.currentData()

    def _on_contour_change(self, event=None):
        """Receive layer model contour value change event and update spinbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.contour.blocker():
            value = self.layer.contour
            self.contourSpinBox.setValue(int(value))

    def _on_selected_label_change(self, event=None):
        """Receive layer model label selection change event and update spinbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.selected_label.blocker():
            value = self.layer.selected_label
            self.selectionSpinBox.setValue(int(value))

    def _on_brush_size_change(self, event=None):
        """Receive layer model brush size change event and update the slider.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.brush_size.blocker():
            value = self.layer.brush_size
            value = np.clip(int(value), 1, 40)
            self.brushSizeSlider.setValue(value)

    def _on_n_dimensional_change(self, event=None):
        """Receive layer model n-dim mode change event and update the checkbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.n_dimensional.blocker():
            self.ndimCheckBox.setChecked(self.layer.n_dimensional)

    def _on_contiguous_change(self, event=None):
        """Receive layer model contiguous change event and update the checkbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.contiguous.blocker():
            self.contigCheckBox.setChecked(self.layer.contiguous)

    def _on_preserve_labels_change(self, event=None):
        """Receive layer model preserve_labels event and update the checkbox.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.preserve_labels.blocker():
            self.preserveLabelsCheckBox.setChecked(self.layer.preserve_labels)

    def _on_color_mode_change(self, event=None):
        """Receive layer model color.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        with self.layer.events.color_mode.blocker():
            # `self.colorModeComboBox.findData` is not returning the correct index.
            for index in range(self.colorModeComboBox.count()):
                if self.layer.color_mode == self.colorModeComboBox.itemData(
                        index):
                    self.colorModeComboBox.setCurrentIndex(index)
                    break

    def _on_brush_shape_change(self, event=None):
        """Receive brush shape change event and update dropdown menu.

        Parameters
        ----------
        event : napari.utils.event.Event
            The napari event that triggered this method.
        """
        with self.layer.events.brush_shape.blocker():
            # `self.brushShapeComboBox.findData` is not returning the correct index.
            for index in range(self.brushShapeComboBox.count()):
                if self.layer.brush_shape == self.brushShapeComboBox.itemData(
                        index):
                    self.brushShapeComboBox.setCurrentIndex(index)
                    break

    def _on_editable_change(self, event=None):
        """Receive layer model editable change event & enable/disable buttons.

        Parameters
        ----------
        event : napari.utils.event.Event, optional
            The napari event that triggered this method.
        """
        disable_with_opacity(
            self,
            ['pick_button', 'paint_button', 'fill_button'],
            self.layer.editable,
        )
コード例 #28
0
ファイル: arrayviewer.py プロジェクト: fumitoh/spyder-modelx
class MxArrayViewer(QWidget):
    """Array Editor Dialog"""
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)  # mx change

        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.data = None
        self.arraywidget = None
        self.stack = None
        self.layout = None
        self.btn_save_and_close = None
        self.btn_close = None
        # Values for 3d array editor
        self.dim_indexes = [{}, {}, {}]
        self.last_dim = 0  # Adjust this for changing the startup dimension

    def setup_and_check(self,
                        data,
                        title='',
                        readonly=False,
                        xlabels=None,
                        ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        readonly = readonly or not self.data.flags.writeable
        is_record_array = data.dtype.names is not None
        is_masked_array = isinstance(data, np.ma.MaskedArray)

        if data.ndim > 3:
            self.error(
                _("Arrays with more than 3 dimensions are not "
                  "supported"))
            return False
        if xlabels is not None and len(xlabels) != self.data.shape[1]:
            self.error(
                _("The 'xlabels' argument length do no match array "
                  "column number"))
            return False
        if ylabels is not None and len(ylabels) != self.data.shape[0]:
            self.error(
                _("The 'ylabels' argument length do no match array row "
                  "number"))
            return False
        if not is_record_array:
            dtn = data.dtype.name
            if dtn == 'object':
                # If the array doesn't have shape, we can't display it
                if data.shape == ():
                    self.error(
                        _("Object arrays without shape are not "
                          "supported"))
                    return False
                # We don't know what's inside these arrays, so we can't handle
                # edits
                self.readonly = readonly = True
            elif (dtn not in SUPPORTED_FORMATS and not dtn.startswith('str')
                  and not dtn.startswith('unicode')):
                arr = _("%s arrays") % data.dtype.name
                self.error(_("%s are currently not supported") % arr)
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = to_text_string(title) + " - " + _("NumPy array")
        else:
            title = _("Array editor")
        if readonly:
            title += ' (' + _('read only') + ')'
        self.setWindowTitle(title)
        # self.resize(600, 500)     # mx change

        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(
                    ArrayEditorWidget(self, data[name], readonly, xlabels,
                                      ylabels))
        elif is_masked_array:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.data, readonly, xlabels, ylabels))
            self.stack.addWidget(
                ArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels))
        elif data.ndim == 3:
            pass
        else:
            self.stack.addWidget(
                ArrayEditorWidget(self, data, readonly, xlabels, ylabels))
        self.arraywidget = self.stack.currentWidget()
        if self.arraywidget:
            self.arraywidget.model.dataChanged.connect(
                self.save_and_close_enable)
        self.stack.currentChanged.connect(self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array or data.ndim == 3:
            if is_record_array:
                btn_layout.addWidget(QLabel(_("Record array fields:")))
                names = []
                for name in data.dtype.names:
                    field = data.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not is_text_string(title):
                            title = repr(title)
                        text += ' - ' + title
                    names.append(text)
            else:
                names = [_('Masked data'), _('Data'), _('Mask')]
            if data.ndim == 3:
                # QSpinBox
                self.index_spin = QSpinBox(self, keyboardTracking=False)
                self.index_spin.valueChanged.connect(self.change_active_widget)
                # QComboBox
                names = [str(i) for i in range(3)]
                ra_combo = QComboBox(self)
                ra_combo.addItems(names)
                ra_combo.currentIndexChanged.connect(self.current_dim_changed)
                # Adding the widgets to layout
                label = QLabel(_("Axis:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(ra_combo)
                self.shape_label = QLabel()
                btn_layout.addWidget(self.shape_label)
                label = QLabel(_("Index:"))
                btn_layout.addWidget(label)
                btn_layout.addWidget(self.index_spin)
                self.slicing_label = QLabel()
                btn_layout.addWidget(self.slicing_label)
                # set the widget to display when launched
                self.current_dim_changed(self.last_dim)
            else:
                ra_combo = QComboBox(self)
                ra_combo.currentIndexChanged.connect(
                    self.stack.setCurrentIndex)
                ra_combo.addItems(names)
                btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel(
                    _("<u>Warning</u>: changes are applied separately"))
                label.setToolTip(_("For performance reasons, changes applied "\
                                   "to masked array won't be reflected in "\
                                   "array's data (and vice-versa)."))
                btn_layout.addWidget(label)

        btn_layout.addStretch()

        if not readonly:
            self.btn_save_and_close = QPushButton(_('Save and Close'))
            self.btn_save_and_close.setDisabled(True)
            self.btn_save_and_close.clicked.connect(self.accept)
            btn_layout.addWidget(self.btn_save_and_close)

        # mx change
        # self.btn_close = QPushButton(_('Close'))
        # self.btn_close.setAutoDefault(True)
        # self.btn_close.setDefault(True)
        # self.btn_close.clicked.connect(self.reject)
        # btn_layout.addWidget(self.btn_close)
        self.layout.addLayout(btn_layout, 2, 0)

        self.setMinimumSize(400, 300)

        # Make the dialog act as a window
        # self.setWindowFlags(Qt.Window)    # mx change

        return True

    @Slot(QModelIndex, QModelIndex)
    def save_and_close_enable(self, left_top, bottom_right):
        """Handle the data change event to enable the save and close button."""
        if self.btn_save_and_close:
            self.btn_save_and_close.setEnabled(True)
            self.btn_save_and_close.setAutoDefault(True)
            self.btn_save_and_close.setDefault(True)

    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)
        self.arraywidget.model.dataChanged.connect(self.save_and_close_enable)

    def change_active_widget(self, index):
        """
        This is implemented for handling negative values in index for
        3d arrays, to give the same behavior as slicing
        """
        string_index = [':'] * 3
        string_index[self.last_dim] = '<font color=red>%i</font>'
        self.slicing_label.setText(
            (r"Slicing: [" + ", ".join(string_index) + "]") % index)
        if index < 0:
            data_index = self.data.shape[self.last_dim] + index
        else:
            data_index = index
        slice_index = [slice(None)] * 3
        slice_index[self.last_dim] = data_index

        stack_index = self.dim_indexes[self.last_dim].get(data_index)
        if stack_index is None:
            stack_index = self.stack.count()
            try:
                self.stack.addWidget(
                    ArrayEditorWidget(self, self.data[tuple(slice_index)]))
            except IndexError:  # Handle arrays of size 0 in one axis
                self.stack.addWidget(ArrayEditorWidget(self, self.data))
            self.dim_indexes[self.last_dim][data_index] = stack_index
            self.stack.update()
        self.stack.setCurrentIndex(stack_index)

    def current_dim_changed(self, index):
        """
        This change the active axis the array editor is plotting over
        in 3D
        """
        self.last_dim = index
        string_size = ['%i'] * 3
        string_size[index] = '<font color=red>%i</font>'
        self.shape_label.setText(
            ('Shape: (' + ', '.join(string_size) + ')    ') % self.data.shape)
        if self.index_spin.value() != 0:
            self.index_spin.setValue(0)
        else:
            # this is done since if the value is currently 0 it does not emit
            # currentIndexChanged(int)
            self.change_active_widget(0)
        self.index_spin.setRange(-self.data.shape[index],
                                 self.data.shape[index] - 1)

    @Slot()
    def accept(self):
        """Reimplement Qt method."""
        try:
            for index in range(self.stack.count()):
                self.stack.widget(index).accept_changes()
            QDialog.accept(self)
        except RuntimeError:
            # Sometimes under CI testing the object the following error appears
            # RuntimeError: wrapped C/C++ object has been deleted
            pass

    def get_value(self):
        """Return modified array -- this is *not* a copy"""
        # It is important to avoid accessing Qt C++ object as it has probably
        # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
        return self.data

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, _("Array editor"), message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    @Slot()
    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
コード例 #29
0
ファイル: main_display.py プロジェクト: hmbui/timechart
class PyDMChartingDisplay(Display):
    def __init__(self, parent=None, args=[], macros=None):
        """
        Create all the widgets, including any child dialogs.

        Parameters
        ----------
        parent : QWidget
            The parent widget of the charting display
        args : list
            The command parameters
        macros : str
            Macros to modify the UI parameters at runtime
        """
        super(PyDMChartingDisplay, self).__init__(parent=parent,
                                                  args=args,
                                                  macros=macros)

        self.channel_map = dict()
        self.setWindowTitle("PyDM Charting Tool")

        self.main_layout = QVBoxLayout()
        self.body_layout = QVBoxLayout()

        self.pv_layout = QHBoxLayout()
        self.pv_name_line_edt = QLineEdit()
        self.pv_name_line_edt.setAcceptDrops(True)
        self.pv_name_line_edt.installEventFilter(self)

        self.pv_protocol_cmb = QComboBox()
        self.pv_protocol_cmb.addItems(["ca://", "archive://"])

        self.pv_connect_push_btn = QPushButton("Connect")
        self.pv_connect_push_btn.clicked.connect(self.add_curve)

        self.tab_panel = QTabWidget()
        self.tab_panel.setMaximumWidth(450)
        self.curve_settings_tab = QWidget()
        self.chart_settings_tab = QWidget()

        self.charting_layout = QHBoxLayout()
        self.chart = PyDMTimePlot(plot_by_timestamps=False, plot_display=self)
        self.chart.setPlotTitle("Time Plot")

        self.splitter = QSplitter()

        self.curve_settings_layout = QVBoxLayout()
        self.curve_settings_layout.setAlignment(Qt.AlignTop)
        self.curve_settings_layout.setSizeConstraint(QLayout.SetMinAndMaxSize)
        self.curve_settings_layout.setSpacing(5)

        self.crosshair_settings_layout = QVBoxLayout()
        self.crosshair_settings_layout.setAlignment(Qt.AlignTop)
        self.crosshair_settings_layout.setSpacing(5)

        self.enable_crosshair_chk = QCheckBox("Enable Crosshair")
        self.cross_hair_coord_lbl = QLabel()

        self.curve_settings_inner_frame = QFrame()
        self.curve_settings_inner_frame.setLayout(self.curve_settings_layout)

        self.curve_settings_scroll = QScrollArea()
        self.curve_settings_scroll.setVerticalScrollBarPolicy(
            Qt.ScrollBarAsNeeded)
        self.curve_settings_scroll.setWidget(self.curve_settings_inner_frame)

        self.curves_tab_layout = QHBoxLayout()
        self.curves_tab_layout.addWidget(self.curve_settings_scroll)

        self.enable_crosshair_chk.setChecked(False)
        self.enable_crosshair_chk.clicked.connect(
            self.handle_enable_crosshair_checkbox_clicked)
        self.enable_crosshair_chk.clicked.emit(False)

        self.chart_settings_layout = QVBoxLayout()
        self.chart_settings_layout.setAlignment(Qt.AlignTop)

        self.chart_layout = QVBoxLayout()
        self.chart_panel = QWidget()

        self.chart_control_layout = QHBoxLayout()
        self.chart_control_layout.setAlignment(Qt.AlignHCenter)
        self.chart_control_layout.setSpacing(10)

        self.view_all_btn = QPushButton("View All")
        self.view_all_btn.clicked.connect(self.handle_view_all_button_clicked)
        self.view_all_btn.setEnabled(False)

        self.auto_scale_btn = QPushButton("Auto Scale")
        self.auto_scale_btn.clicked.connect(self.handle_auto_scale_btn_clicked)
        self.auto_scale_btn.setEnabled(False)

        self.reset_chart_btn = QPushButton("Reset")
        self.reset_chart_btn.clicked.connect(
            self.handle_reset_chart_btn_clicked)
        self.reset_chart_btn.setEnabled(False)

        self.resume_chart_text = "Resume"
        self.pause_chart_text = "Pause"
        self.pause_chart_btn = QPushButton(self.pause_chart_text)
        self.pause_chart_btn.clicked.connect(
            self.handle_pause_chart_btn_clicked)

        self.title_settings_layout = QVBoxLayout()
        self.title_settings_layout.setSpacing(10)

        self.title_settings_grpbx = QGroupBox()
        self.title_settings_grpbx.setFixedHeight(150)

        self.import_data_btn = QPushButton("Import Data...")
        self.import_data_btn.clicked.connect(
            self.handle_import_data_btn_clicked)

        self.export_data_btn = QPushButton("Export Data...")
        self.export_data_btn.clicked.connect(
            self.handle_export_data_btn_clicked)

        self.chart_title_lbl = QLabel(text="Chart Title")
        self.chart_title_line_edt = QLineEdit()
        self.chart_title_line_edt.setText(self.chart.getPlotTitle())
        self.chart_title_line_edt.textChanged.connect(
            self.handle_title_text_changed)

        self.chart_change_axis_settings_btn = QPushButton(
            text="Change Axis Settings...")
        self.chart_change_axis_settings_btn.clicked.connect(
            self.handle_change_axis_settings_clicked)

        self.update_datetime_timer = QTimer(self)
        self.update_datetime_timer.timeout.connect(
            self.handle_update_datetime_timer_timeout)

        self.chart_sync_mode_layout = QVBoxLayout()
        self.chart_sync_mode_layout.setSpacing(5)

        self.chart_sync_mode_grpbx = QGroupBox("Data Sampling Mode")
        self.chart_sync_mode_grpbx.setFixedHeight(80)

        self.chart_sync_mode_sync_radio = QRadioButton("Synchronous")
        self.chart_sync_mode_async_radio = QRadioButton("Asynchronous")
        self.chart_sync_mode_async_radio.setChecked(True)

        self.graph_drawing_settings_layout = QVBoxLayout()

        self.chart_redraw_rate_lbl = QLabel("Redraw Rate (Hz)")
        self.chart_redraw_rate_spin = QSpinBox()
        self.chart_redraw_rate_spin.setRange(MIN_REDRAW_RATE_HZ,
                                             MAX_REDRAW_RATE_HZ)
        self.chart_redraw_rate_spin.setValue(DEFAULT_REDRAW_RATE_HZ)
        self.chart_redraw_rate_spin.valueChanged.connect(
            self.handle_redraw_rate_changed)

        self.chart_data_sampling_rate_lbl = QLabel(
            "Asynchronous Data Sampling Rate (Hz)")
        self.chart_data_async_sampling_rate_spin = QSpinBox()
        self.chart_data_async_sampling_rate_spin.setRange(
            MIN_DATA_SAMPLING_RATE_HZ, MAX_DATA_SAMPLING_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.setValue(
            DEFAULT_DATA_SAMPLING_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.valueChanged.connect(
            self.handle_data_sampling_rate_changed)
        self.chart_data_sampling_rate_lbl.hide()
        self.chart_data_async_sampling_rate_spin.hide()

        self.chart_limit_time_span_layout = QHBoxLayout()
        self.chart_limit_time_span_layout.setSpacing(5)

        self.limit_time_plan_text = "Limit Time Span"
        self.chart_limit_time_span_chk = QCheckBox(self.limit_time_plan_text)
        self.chart_limit_time_span_chk.hide()
        self.chart_limit_time_span_lbl = QLabel("Hours : Minutes : Seconds")
        self.chart_limit_time_span_hours_line_edt = QLineEdit()
        self.chart_limit_time_span_minutes_line_edt = QLineEdit()
        self.chart_limit_time_span_seconds_line_edt = QLineEdit()
        self.chart_limit_time_span_activate_btn = QPushButton("Apply")
        self.chart_limit_time_span_activate_btn.setDisabled(True)

        self.chart_ring_buffer_size_lbl = QLabel("Ring Buffer Size")
        self.chart_ring_buffer_size_edt = QLineEdit()
        self.chart_ring_buffer_size_edt.installEventFilter(self)
        self.chart_ring_buffer_size_edt.textChanged.connect(
            self.handle_buffer_size_changed)
        self.chart_ring_buffer_size_edt.setText(str(DEFAULT_BUFFER_SIZE))

        self.show_legend_chk = QCheckBox("Show Legend")
        self.show_legend_chk.setChecked(self.chart.showLegend)
        self.show_legend_chk.clicked.connect(
            self.handle_show_legend_checkbox_clicked)

        self.graph_background_color_layout = QFormLayout()

        self.background_color_lbl = QLabel("Graph Background Color ")
        self.background_color_btn = QPushButton()
        self.background_color_btn.setStyleSheet(
            "background-color: " + self.chart.getBackgroundColor().name())
        self.background_color_btn.setContentsMargins(10, 0, 5, 5)
        self.background_color_btn.setMaximumWidth(20)
        self.background_color_btn.clicked.connect(
            self.handle_background_color_button_clicked)

        self.axis_settings_layout = QVBoxLayout()
        self.axis_settings_layout.setSpacing(5)

        self.show_x_grid_chk = QCheckBox("Show x Grid")
        self.show_x_grid_chk.setChecked(self.chart.showXGrid)
        self.show_x_grid_chk.clicked.connect(
            self.handle_show_x_grid_checkbox_clicked)

        self.show_y_grid_chk = QCheckBox("Show y Grid")
        self.show_y_grid_chk.setChecked(self.chart.showYGrid)
        self.show_y_grid_chk.clicked.connect(
            self.handle_show_y_grid_checkbox_clicked)

        self.axis_color_lbl = QLabel("Axis and Grid Color")
        self.axis_color_lbl.setEnabled(False)

        self.axis_color_btn = QPushButton()
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          DEFAULT_CHART_AXIS_COLOR.name())
        self.axis_color_btn.setContentsMargins(10, 0, 5, 5)
        self.axis_color_btn.setMaximumWidth(20)
        self.axis_color_btn.clicked.connect(
            self.handle_axis_color_button_clicked)
        self.axis_color_btn.setEnabled(False)

        self.grid_opacity_lbl = QLabel("Grid Opacity")
        self.grid_opacity_lbl.setEnabled(False)

        self.grid_opacity_slr = QSlider(Qt.Horizontal)
        self.grid_opacity_slr.setFocusPolicy(Qt.StrongFocus)
        self.grid_opacity_slr.setRange(0, 10)
        self.grid_opacity_slr.setValue(5)
        self.grid_opacity_slr.setTickInterval(1)
        self.grid_opacity_slr.setSingleStep(1)
        self.grid_opacity_slr.setTickPosition(QSlider.TicksBelow)
        self.grid_opacity_slr.valueChanged.connect(
            self.handle_grid_opacity_slider_mouse_release)
        self.grid_opacity_slr.setEnabled(False)

        self.reset_chart_settings_btn = QPushButton("Reset Chart Settings")
        self.reset_chart_settings_btn.clicked.connect(
            self.handle_reset_chart_settings_btn_clicked)

        self.curve_checkbox_panel = QWidget()

        self.graph_drawing_settings_grpbx = QGroupBox()
        self.graph_drawing_settings_grpbx.setFixedHeight(270)

        self.axis_settings_grpbx = QGroupBox()
        self.axis_settings_grpbx.setFixedHeight(180)

        self.app = QApplication.instance()
        self.setup_ui()

        self.curve_settings_disp = None
        self.axis_settings_disp = None
        self.chart_data_export_disp = None
        self.chart_data_import_disp = None
        self.grid_alpha = 5
        self.time_span_limit_hours = None
        self.time_span_limit_minutes = None
        self.time_span_limit_seconds = None
        self.data_sampling_mode = ASYNC_DATA_SAMPLING

    def minimumSizeHint(self):
        """
        The minimum recommended size of the main window.
        """
        return QSize(1490, 800)

    def ui_filepath(self):
        """
        The path to the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def ui_filename(self):
        """
        The name the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def setup_ui(self):
        """
        Initialize the widgets and layouts.
        """
        self.setLayout(self.main_layout)

        self.pv_layout.addWidget(self.pv_protocol_cmb)
        self.pv_layout.addWidget(self.pv_name_line_edt)
        self.pv_layout.addWidget(self.pv_connect_push_btn)
        QTimer.singleShot(0, self.pv_name_line_edt.setFocus)

        self.curve_settings_tab.setLayout(self.curves_tab_layout)
        self.chart_settings_tab.setLayout(self.chart_settings_layout)
        self.setup_chart_settings_layout()

        self.tab_panel.addTab(self.curve_settings_tab, "Curves")
        self.tab_panel.addTab(self.chart_settings_tab, "Chart")
        self.tab_panel.hide()

        self.crosshair_settings_layout.addWidget(self.enable_crosshair_chk)
        self.crosshair_settings_layout.addWidget(self.cross_hair_coord_lbl)

        self.chart_control_layout.addWidget(self.auto_scale_btn)
        self.chart_control_layout.addWidget(self.view_all_btn)
        self.chart_control_layout.addWidget(self.reset_chart_btn)
        self.chart_control_layout.addWidget(self.pause_chart_btn)
        self.chart_control_layout.addLayout(self.crosshair_settings_layout)
        self.chart_control_layout.addWidget(self.import_data_btn)
        self.chart_control_layout.addWidget(self.export_data_btn)

        self.chart_control_layout.setStretch(4, 15)
        self.chart_control_layout.insertSpacing(5, 350)

        self.chart_layout.addWidget(self.chart)
        self.chart_layout.addLayout(self.chart_control_layout)

        self.chart_panel.setLayout(self.chart_layout)

        self.splitter.addWidget(self.chart_panel)
        self.splitter.addWidget(self.tab_panel)
        self.splitter.setStretchFactor(0, 0)
        self.splitter.setStretchFactor(1, 1)

        self.charting_layout.addWidget(self.splitter)

        self.body_layout.addLayout(self.pv_layout)
        self.body_layout.addLayout(self.charting_layout)
        self.body_layout.addLayout(self.chart_control_layout)
        self.main_layout.addLayout(self.body_layout)

        self.enable_chart_control_buttons(False)

    def setup_chart_settings_layout(self):
        self.chart_sync_mode_sync_radio.toggled.connect(
            partial(self.handle_sync_mode_radio_toggle,
                    self.chart_sync_mode_sync_radio))
        self.chart_sync_mode_async_radio.toggled.connect(
            partial(self.handle_sync_mode_radio_toggle,
                    self.chart_sync_mode_async_radio))

        self.title_settings_layout.addWidget(self.chart_title_lbl)
        self.title_settings_layout.addWidget(self.chart_title_line_edt)
        self.title_settings_layout.addWidget(self.show_legend_chk)
        self.title_settings_layout.addWidget(
            self.chart_change_axis_settings_btn)
        self.title_settings_grpbx.setLayout(self.title_settings_layout)
        self.chart_settings_layout.addWidget(self.title_settings_grpbx)

        self.chart_sync_mode_layout.addWidget(self.chart_sync_mode_sync_radio)
        self.chart_sync_mode_layout.addWidget(self.chart_sync_mode_async_radio)
        self.chart_sync_mode_grpbx.setLayout(self.chart_sync_mode_layout)
        self.chart_settings_layout.addWidget(self.chart_sync_mode_grpbx)

        self.chart_settings_layout.addWidget(self.chart_sync_mode_grpbx)

        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_lbl)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_hours_line_edt)

        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_minutes_line_edt)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_seconds_line_edt)
        self.chart_limit_time_span_layout.addWidget(
            self.chart_limit_time_span_activate_btn)

        self.chart_limit_time_span_lbl.hide()
        self.chart_limit_time_span_hours_line_edt.hide()
        self.chart_limit_time_span_minutes_line_edt.hide()
        self.chart_limit_time_span_seconds_line_edt.hide()
        self.chart_limit_time_span_activate_btn.hide()

        self.chart_limit_time_span_hours_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)
        self.chart_limit_time_span_minutes_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)
        self.chart_limit_time_span_seconds_line_edt.textChanged.connect(
            self.handle_time_span_edt_text_changed)

        self.chart_limit_time_span_chk.clicked.connect(
            self.handle_limit_time_span_checkbox_clicked)
        self.chart_limit_time_span_activate_btn.clicked.connect(
            self.handle_chart_limit_time_span_activate_btn_clicked)
        self.chart_limit_time_span_activate_btn.installEventFilter(self)

        self.graph_background_color_layout.addRow(self.background_color_lbl,
                                                  self.background_color_btn)

        self.graph_drawing_settings_layout.addLayout(
            self.graph_background_color_layout)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_redraw_rate_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_redraw_rate_spin)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_data_sampling_rate_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_data_async_sampling_rate_spin)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_limit_time_span_chk)
        self.graph_drawing_settings_layout.addLayout(
            self.chart_limit_time_span_layout)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_ring_buffer_size_lbl)
        self.graph_drawing_settings_layout.addWidget(
            self.chart_ring_buffer_size_edt)
        self.graph_drawing_settings_grpbx.setLayout(
            self.graph_drawing_settings_layout)

        self.axis_settings_layout.addWidget(self.show_x_grid_chk)
        self.axis_settings_layout.addWidget(self.show_y_grid_chk)
        self.axis_settings_layout.addWidget(self.axis_color_lbl)
        self.axis_settings_layout.addWidget(self.axis_color_btn)
        self.axis_settings_layout.addWidget(self.grid_opacity_lbl)
        self.axis_settings_layout.addWidget(self.grid_opacity_slr)
        self.axis_settings_grpbx.setLayout(self.axis_settings_layout)

        self.chart_settings_layout.addWidget(self.graph_drawing_settings_grpbx)
        self.chart_settings_layout.addWidget(self.axis_settings_grpbx)
        self.chart_settings_layout.addWidget(self.reset_chart_settings_btn)

        self.chart_sync_mode_async_radio.toggled.emit(True)
        self.update_datetime_timer.start(1000)

    def eventFilter(self, obj, event):
        """
        Handle key and mouse events for any applicable widget.

        Parameters
        ----------
        obj : QWidget
            The current widget that accepts the event
        event : QEvent
            The key or mouse event to handle

        Returns
        -------
            True if the event was handled successfully; False otherwise
        """
        if obj == self.pv_name_line_edt and event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
                self.add_curve()
                return True
        elif obj == self.chart_limit_time_span_activate_btn and event.type(
        ) == QEvent.KeyPress:
            if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
                self.handle_chart_limit_time_span_activate_btn_clicked()
                return True
        elif obj == self.chart_ring_buffer_size_edt:
            if event.type() == QEvent.KeyPress and (event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return) or \
                    event.type() == QEvent.FocusOut:
                try:
                    buffer_size = int(self.chart_ring_buffer_size_edt.text())
                    if buffer_size < MINIMUM_BUFFER_SIZE:
                        self.chart_ring_buffer_size_edt.setText(
                            str(MINIMUM_BUFFER_SIZE))
                except ValueError:
                    display_message_box(QMessageBox.Critical, "Invalid Values",
                                        "Only integer values are accepted.")
                return True
        return super(PyDMChartingDisplay, self).eventFilter(obj, event)

    def add_curve(self):
        """
        Add a new curve to the chart.
        """
        pv_name = self._get_full_pv_name(self.pv_name_line_edt.text())
        color = random_color()
        for k, v in self.channel_map.items():
            if color == v.color:
                color = random_color()

        self.add_y_channel(pv_name=pv_name, curve_name=pv_name, color=color)

    def handle_enable_crosshair_checkbox_clicked(self, is_checked):
        self.chart.enableCrosshair(is_checked)
        self.cross_hair_coord_lbl.setVisible(is_checked)

    def add_y_channel(self,
                      pv_name,
                      curve_name,
                      color,
                      line_style=Qt.SolidLine,
                      line_width=2,
                      symbol=None,
                      symbol_size=None):
        if pv_name in self.channel_map:
            logger.error("'{0}' has already been added.".format(pv_name))
            return

        curve = self.chart.addYChannel(y_channel=pv_name,
                                       name=curve_name,
                                       color=color,
                                       lineStyle=line_style,
                                       lineWidth=line_width,
                                       symbol=symbol,
                                       symbolSize=symbol_size)
        self.channel_map[pv_name] = curve
        self.generate_pv_controls(pv_name, color)

        self.enable_chart_control_buttons()
        self.app.establish_widget_connections(self)

    def generate_pv_controls(self, pv_name, curve_color):
        """
        Generate a set of widgets to manage the appearance of a curve. The set of widgets includes:
            1. A checkbox which shows the curve on the chart if checked, and hide the curve if not checked
            2. Two buttons -- Modify... and Remove. Modify... will bring up the Curve Settings dialog. Remove will
               delete the curve from the chart
        This set of widgets will be hidden initially, until the first curve is plotted.

        Parameters
        ----------
        pv_name: str
            The name of the PV the current curve is being plotted for

        curve_color : QColor
            The color of the curve to paint for the checkbox label to help the user track the curve to the checkbox
        """
        checkbox = QCheckBox()
        checkbox.setObjectName(pv_name)

        palette = checkbox.palette()
        palette.setColor(QPalette.Active, QPalette.WindowText, curve_color)
        checkbox.setPalette(palette)

        display_name = pv_name.split("://")[1]
        if len(display_name) > MAX_DISPLAY_PV_NAME_LENGTH:
            # Only display max allowed number of characters of the PV Name
            display_name = display_name[:int(MAX_DISPLAY_PV_NAME_LENGTH / 2) - 1] + "..." + \
                           display_name[-int(MAX_DISPLAY_PV_NAME_LENGTH / 2) + 2:]

        checkbox.setText(display_name)

        data_text = QLabel()
        data_text.setObjectName(pv_name)
        data_text.setPalette(palette)

        checkbox.setChecked(True)
        checkbox.clicked.connect(
            partial(self.handle_curve_chkbox_toggled, checkbox))

        curve_btn_layout = QHBoxLayout()

        modify_curve_btn = QPushButton("Modify...")
        modify_curve_btn.setObjectName(pv_name)
        modify_curve_btn.setMaximumWidth(100)
        modify_curve_btn.clicked.connect(
            partial(self.display_curve_settings_dialog, pv_name))

        focus_curve_btn = QPushButton("Focus")
        focus_curve_btn.setObjectName(pv_name)
        focus_curve_btn.setMaximumWidth(100)
        focus_curve_btn.clicked.connect(partial(self.focus_curve, pv_name))

        annotate_curve_btn = QPushButton("Annotate...")
        annotate_curve_btn.setObjectName(pv_name)
        annotate_curve_btn.setMaximumWidth(100)
        annotate_curve_btn.clicked.connect(
            partial(self.annotate_curve, pv_name))

        remove_curve_btn = QPushButton("Remove")
        remove_curve_btn.setObjectName(pv_name)
        remove_curve_btn.setMaximumWidth(100)
        remove_curve_btn.clicked.connect(partial(self.remove_curve, pv_name))

        curve_btn_layout.addWidget(modify_curve_btn)
        curve_btn_layout.addWidget(focus_curve_btn)
        curve_btn_layout.addWidget(annotate_curve_btn)
        curve_btn_layout.addWidget(remove_curve_btn)

        individual_curve_layout = QVBoxLayout()
        individual_curve_layout.addWidget(checkbox)
        individual_curve_layout.addWidget(data_text)
        individual_curve_layout.addLayout(curve_btn_layout)

        size_policy = QSizePolicy()
        size_policy.setVerticalPolicy(QSizePolicy.Fixed)
        individual_curve_grpbx = QGroupBox()
        individual_curve_grpbx.setSizePolicy(size_policy)

        individual_curve_grpbx.setObjectName(pv_name)
        individual_curve_grpbx.setLayout(individual_curve_layout)

        self.curve_settings_layout.addWidget(individual_curve_grpbx)
        self.tab_panel.show()

    def handle_curve_chkbox_toggled(self, checkbox):
        """
        Handle a checkbox's checked and unchecked events.

        If a checkbox is checked, find the curve from the channel map. If found, re-draw the curve with its previous
        appearance settings.

        If a checkbox is unchecked, remove the curve from the chart, but keep the cached data in the channel map.

        Parameters
        ----------
        checkbox : QCheckBox
            The current checkbox being toggled
        """
        pv_name = self._get_full_pv_name(checkbox.text())

        if checkbox.isChecked():
            curve = self.channel_map.get(pv_name, None)
            if curve:
                self.chart.addLegendItem(curve, pv_name,
                                         self.show_legend_chk.isChecked())
                curve.show()
        else:
            curve = self.chart.findCurve(pv_name)
            if curve:
                curve.hide()
                self.chart.removeLegendItem(pv_name)

    def display_curve_settings_dialog(self, pv_name):
        """
        Bring up the Curve Settings dialog to modify the appearance of a curve.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for

        """
        self.curve_settings_disp = CurveSettingsDisplay(self, pv_name)
        self.curve_settings_disp.show()

    def focus_curve(self, pv_name):
        curve = self.chart.findCurve(pv_name)
        if curve:
            self.chart.plotItem.setYRange(curve.minY, curve.maxY, padding=0)

    def annotate_curve(self, pv_name):
        curve = self.chart.findCurve(pv_name)
        if curve:
            annot = TextItem(
                html=
                '<div style="text-align: center"><span style="color: #FFF;">This is the'
                '</span><br><span style="color: #FF0; font-size: 16pt;">PEAK</span></div>',
                anchor=(-0.3, 0.5),
                border='w',
                fill=(0, 0, 255, 100))
            annot = TextItem("test", anchor=(-0.3, 0.5))
            self.chart.annotateCurve(curve, annot)

    def remove_curve(self, pv_name):
        """
        Remove a curve from the chart permanently. This will also clear the channel map cache from retaining the
        removed curve's appearance settings.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for
        """
        curve = self.chart.findCurve(pv_name)
        if curve:
            self.chart.removeYChannel(curve)
            del self.channel_map[pv_name]
            self.chart.removeLegendItem(pv_name)

            widgets = self.findChildren(
                (QCheckBox, QLabel, QPushButton, QGroupBox), pv_name)
            for w in widgets:
                w.deleteLater()

        if len(self.chart.getCurves()) < 1:
            self.enable_chart_control_buttons(False)
            self.show_legend_chk.setChecked(False)

    def handle_title_text_changed(self, new_text):
        self.chart.setPlotTitle(new_text)

    def handle_change_axis_settings_clicked(self):
        self.axis_settings_disp = AxisSettingsDisplay(self)
        self.axis_settings_disp.show()

    def handle_limit_time_span_checkbox_clicked(self, is_checked):
        self.chart_limit_time_span_lbl.setVisible(is_checked)
        self.chart_limit_time_span_hours_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_minutes_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_seconds_line_edt.setVisible(is_checked)
        self.chart_limit_time_span_activate_btn.setVisible(is_checked)

        self.chart_ring_buffer_size_lbl.setDisabled(is_checked)
        self.chart_ring_buffer_size_edt.setDisabled(is_checked)

        if not is_checked:
            self.chart_limit_time_span_chk.setText(self.limit_time_plan_text)

    def handle_time_span_edt_text_changed(self, new_text):
        try:
            self.time_span_limit_hours = int(
                self.chart_limit_time_span_hours_line_edt.text())
            self.time_span_limit_minutes = int(
                self.chart_limit_time_span_minutes_line_edt.text())
            self.time_span_limit_seconds = int(
                self.chart_limit_time_span_seconds_line_edt.text())
        except ValueError as e:
            self.time_span_limit_hours = None
            self.time_span_limit_minutes = None
            self.time_span_limit_seconds = None

        if self.time_span_limit_hours is not None and self.time_span_limit_minutes is not None and \
                self.time_span_limit_seconds is not None:
            self.chart_limit_time_span_activate_btn.setEnabled(True)
        else:
            self.chart_limit_time_span_activate_btn.setEnabled(False)

    def handle_chart_limit_time_span_activate_btn_clicked(self):
        if self.time_span_limit_hours is None or self.time_span_limit_minutes is None or \
                self.time_span_limit_seconds is None:
            display_message_box(
                QMessageBox.Critical, "Invalid Values",
                "Hours, minutes, and seconds expect only integer values.")
        else:
            timeout_milliseconds = (self.time_span_limit_hours * 3600 +
                                    self.time_span_limit_minutes * 60 +
                                    self.time_span_limit_seconds) * 1000
            self.chart.setTimeSpan(timeout_milliseconds / 1000.0)
            self.chart_ring_buffer_size_edt.setText(
                str(self.chart.getBufferSize()))

    def handle_buffer_size_changed(self, new_buffer_size):
        try:
            if new_buffer_size and int(new_buffer_size) > MINIMUM_BUFFER_SIZE:
                self.chart.setBufferSize(new_buffer_size)
        except ValueError:
            display_message_box(QMessageBox.Critical, "Invalid Values",
                                "Only integer values are accepted.")

    def handle_redraw_rate_changed(self, new_redraw_rate):
        self.chart.maxRedrawRate = new_redraw_rate

    def handle_data_sampling_rate_changed(self, new_data_sampling_rate):
        # The chart expects the value in milliseconds
        sampling_rate_seconds = 1 / new_data_sampling_rate
        self.chart.setUpdateInterval(sampling_rate_seconds)

    def handle_background_color_button_clicked(self):
        selected_color = QColorDialog.getColor()
        self.chart.setBackgroundColor(selected_color)
        self.background_color_btn.setStyleSheet("background-color: " +
                                                selected_color.name())

    def handle_axis_color_button_clicked(self):
        selected_color = QColorDialog.getColor()
        self.chart.setAxisColor(selected_color)
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          selected_color.name())

    def handle_grid_opacity_slider_mouse_release(self):
        self.grid_alpha = float(self.grid_opacity_slr.value()) / 10.0
        self.chart.setShowXGrid(self.show_x_grid_chk.isChecked(),
                                self.grid_alpha)
        self.chart.setShowYGrid(self.show_y_grid_chk.isChecked(),
                                self.grid_alpha)

    def handle_show_x_grid_checkbox_clicked(self, is_checked):
        self.chart.setShowXGrid(is_checked, self.grid_alpha)

        self.axis_color_lbl.setEnabled(is_checked
                                       or self.show_y_grid_chk.isChecked())
        self.axis_color_btn.setEnabled(is_checked
                                       or self.show_y_grid_chk.isChecked())
        self.grid_opacity_lbl.setEnabled(is_checked
                                         or self.show_y_grid_chk.isChecked())
        self.grid_opacity_slr.setEnabled(is_checked
                                         or self.show_y_grid_chk.isChecked())

    def handle_show_y_grid_checkbox_clicked(self, is_checked):
        self.chart.setShowYGrid(is_checked, self.grid_alpha)

        self.axis_color_lbl.setEnabled(is_checked
                                       or self.show_x_grid_chk.isChecked())
        self.axis_color_btn.setEnabled(is_checked
                                       or self.show_x_grid_chk.isChecked())
        self.grid_opacity_lbl.setEnabled(is_checked
                                         or self.show_x_grid_chk.isChecked())
        self.grid_opacity_slr.setEnabled(is_checked
                                         or self.show_x_grid_chk.isChecked())

    def handle_show_legend_checkbox_clicked(self, is_checked):
        self.chart.setShowLegend(is_checked)

    def handle_export_data_btn_clicked(self):
        self.chart_data_export_disp = ChartDataExportDisplay(self)
        self.chart_data_export_disp.show()

    def handle_import_data_btn_clicked(self):
        open_file_info = QFileDialog.getOpenFileName(self,
                                                     caption="Save File",
                                                     filter="*." +
                                                     IMPORT_FILE_FORMAT)
        open_file_name = open_file_info[0]
        if open_file_name:
            importer = SettingsImporter(self)
            importer.import_settings(open_file_name)

    def handle_sync_mode_radio_toggle(self, radio_btn):
        if radio_btn.isChecked():
            if radio_btn.text() == "Synchronous":
                self.data_sampling_mode = SYNC_DATA_SAMPLING

                self.chart_data_sampling_rate_lbl.hide()
                self.chart_data_async_sampling_rate_spin.hide()

                self.chart.resetTimeSpan()
                self.chart_limit_time_span_chk.setChecked(False)
                self.chart_limit_time_span_chk.clicked.emit(False)
                self.chart_limit_time_span_chk.hide()
                self.graph_drawing_settings_grpbx.setFixedHeight(180)

                self.chart.setUpdatesAsynchronously(False)
            elif radio_btn.text() == "Asynchronous":
                self.data_sampling_mode = ASYNC_DATA_SAMPLING

                self.chart_data_sampling_rate_lbl.show()
                self.chart_data_async_sampling_rate_spin.show()
                self.chart_limit_time_span_chk.show()
                self.graph_drawing_settings_grpbx.setFixedHeight(270)

                self.chart.setUpdatesAsynchronously(True)
        self.app.establish_widget_connections(self)

    def handle_auto_scale_btn_clicked(self):
        self.chart.resetAutoRangeX()
        self.chart.resetAutoRangeY()

    def handle_view_all_button_clicked(self):
        self.chart.getViewBox().autoRange()

    def handle_pause_chart_btn_clicked(self):
        if self.chart.pausePlotting():
            self.pause_chart_btn.setText(self.pause_chart_text)
        else:
            self.pause_chart_btn.setText(self.resume_chart_text)

    def handle_reset_chart_btn_clicked(self):
        self.chart.getViewBox().setXRange(DEFAULT_X_MIN, 0)
        self.chart.resetAutoRangeY()

    @Slot()
    def handle_reset_chart_settings_btn_clicked(self):
        self.chart_ring_buffer_size_edt.setText(str(DEFAULT_BUFFER_SIZE))

        self.chart_redraw_rate_spin.setValue(DEFAULT_REDRAW_RATE_HZ)
        self.chart_data_async_sampling_rate_spin.setValue(
            DEFAULT_DATA_SAMPLING_RATE_HZ)
        self.chart_data_sampling_rate_lbl.hide()
        self.chart_data_async_sampling_rate_spin.hide()

        self.chart_sync_mode_async_radio.setChecked(True)
        self.chart_sync_mode_async_radio.toggled.emit(True)

        self.chart_limit_time_span_chk.setChecked(False)
        self.chart_limit_time_span_chk.setText(self.limit_time_plan_text)
        self.chart_limit_time_span_chk.clicked.emit(False)

        self.chart.setUpdatesAsynchronously(True)
        self.chart.resetTimeSpan()
        self.chart.resetUpdateInterval()
        self.chart.setBufferSize(DEFAULT_BUFFER_SIZE)

        self.chart.setBackgroundColor(DEFAULT_CHART_BACKGROUND_COLOR)
        self.background_color_btn.setStyleSheet(
            "background-color: " + DEFAULT_CHART_BACKGROUND_COLOR.name())

        self.chart.setAxisColor(DEFAULT_CHART_AXIS_COLOR)
        self.axis_color_btn.setStyleSheet("background-color: " +
                                          DEFAULT_CHART_AXIS_COLOR.name())

        self.grid_opacity_slr.setValue(5)

        self.show_x_grid_chk.setChecked(False)
        self.show_x_grid_chk.clicked.emit(False)

        self.show_y_grid_chk.setChecked(False)
        self.show_y_grid_chk.clicked.emit(False)

        self.show_legend_chk.setChecked(False)

        self.chart.setShowXGrid(False)
        self.chart.setShowYGrid(False)
        self.chart.setShowLegend(False)

    def enable_chart_control_buttons(self, enabled=True):
        self.auto_scale_btn.setEnabled(enabled)
        self.view_all_btn.setEnabled(enabled)
        self.reset_chart_btn.setEnabled(enabled)
        self.pause_chart_btn.setText(self.pause_chart_text)
        self.pause_chart_btn.setEnabled(enabled)
        self.export_data_btn.setEnabled(enabled)

    def _get_full_pv_name(self, pv_name):
        """
        Append the protocol to the PV Name.

        Parameters
        ----------
        pv_name : str
            The name of the PV the curve is being plotted for
        """
        if pv_name and "://" not in pv_name:
            pv_name = ''.join([self.pv_protocol_cmb.currentText(), pv_name])
        return pv_name

    def handle_update_datetime_timer_timeout(self):
        current_label = self.chart.getBottomAxisLabel()
        new_label = "Current Time: " + PyDMChartingDisplay.get_current_datetime(
        )

        if X_AXIS_LABEL_SEPARATOR in current_label:
            current_label = current_label[current_label.
                                          find(X_AXIS_LABEL_SEPARATOR) +
                                          len(X_AXIS_LABEL_SEPARATOR):]
            new_label += X_AXIS_LABEL_SEPARATOR + current_label

        self.chart.setLabel("bottom", text=new_label)

    def update_curve_data(self, curve):
        """
        Determine if the PV is active. If not, disable the related PV controls. If the PV is active, update the PV
        controls' states.

        Parameters
        ----------
        curve : PlotItem
           A PlotItem, i.e. a plot, to draw on the chart.
        """
        pv_name = curve.name()
        max_x = self.chart.getViewBox().viewRange()[1][0]
        max_y = self.chart.getViewBox().viewRange()[1][1]
        current_y = curve.data_buffer[1, -1]

        widgets = self.findChildren((QCheckBox, QLabel, QPushButton), pv_name)
        for w in widgets:
            if np.isnan(current_y):
                if isinstance(w, QCheckBox):
                    w.setChecked(False)
            else:
                if isinstance(w, QCheckBox) and not w.isEnabled():
                    w.setChecked(True)
                if isinstance(w, QLabel):
                    w.clear()
                    w.setText(
                        "(yMin = {0:.3f}, yMax = {1:.3f}) y = {2:.3f}".format(
                            max_x, max_y, current_y))
                    w.show()
            w.setEnabled(not np.isnan(current_y))

            if isinstance(w, QPushButton) and w.text() == "Remove":
                # Enable the Remove button to make removing inactive PVs possible anytime
                w.setEnabled(True)

    def show_mouse_coordinates(self, x, y):
        self.cross_hair_coord_lbl.clear()
        self.cross_hair_coord_lbl.setText("x = {0:.3f}, y = {1:.3f}".format(
            x, y))

    @staticmethod
    def get_current_datetime():
        current_date = datetime.datetime.now().strftime("%b %d, %Y")
        current_time = datetime.datetime.now().strftime("%H:%M:%S")
        current_datetime = current_time + ' (' + current_date + ')'

        return current_datetime

    @property
    def gridAlpha(self):
        return self.grid_alpha
コード例 #30
0
ファイル: qt_labels_layer.py プロジェクト: quantumjot/napari
class QtLabelsControls(QtLayerControls):
    """Qt view and controls for the napari Labels layer.

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

    Attributes
    ----------
    button_group : qtpy.QtWidgets.QButtonGroup
        Button group of labels layer modes: PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    colormapUpdate : qtpy.QtWidgets.QPushButton
        Button to update colormap of label layer.
    contigCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to control if label layer is contiguous.
    fill_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select FILL mode on Labels layer.
    grid_layout : qtpy.QtWidgets.QGridLayout
        Layout of Qt widget controls for the layer.
    layer : napari.layers.Labels
        An instance of a napari Labels layer.
    ndimCheckBox : qtpy.QtWidgets.QCheckBox
        Checkbox to control if label layer is n-dimensional.
    paint_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAINT mode on Labels layer.
    panzoom_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PAN_ZOOM mode on Labels layer.
    pick_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select PICKER mode on Labels layer.
    erase_button : qtpy.QtWidgets.QtModeRadioButton
        Button to select ERASE mode on Labels layer.
    selectionSpinBox : qtpy.QtWidgets.QSpinBox
        Widget to select a specfic label by its index.

    Raises
    ------
    ValueError
        Raise error if label mode is not PAN_ZOOM, PICKER, PAINT, ERASE, or
        FILL.
    """
    def __init__(self, layer):
        super().__init__(layer)

        self.layer.events.mode.connect(self._on_mode_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.layer.events.editable.connect(self._on_editable_change)
        self.layer.events.preserve_labels.connect(
            self._on_preserve_labels_change)

        # selection spinbox
        self.selectionSpinBox = QSpinBox()
        self.selectionSpinBox.setKeyboardTracking(False)
        self.selectionSpinBox.setSingleStep(1)
        self.selectionSpinBox.setMinimum(0)
        self.selectionSpinBox.setMaximum(2147483647)
        self.selectionSpinBox.valueChanged.connect(self.changeSelection)
        self.selectionSpinBox.setAlignment(Qt.AlignCenter)
        self._on_selection_change()

        sld = QSlider(Qt.Horizontal)
        sld.setFocusPolicy(Qt.NoFocus)
        sld.setMinimum(1)
        sld.setMaximum(40)
        sld.setSingleStep(1)
        sld.valueChanged.connect(self.changeSize)
        self.brushSizeSlider = sld
        self._on_brush_size_change()

        contig_cb = QCheckBox()
        contig_cb.setToolTip('contiguous editing')
        contig_cb.stateChanged.connect(self.change_contig)
        self.contigCheckBox = contig_cb
        self._on_contig_change()

        ndim_cb = QCheckBox()
        ndim_cb.setToolTip('n-dimensional editing')
        ndim_cb.stateChanged.connect(self.change_ndim)
        self.ndimCheckBox = ndim_cb
        self._on_n_dim_change()

        preserve_labels_cb = QCheckBox()
        preserve_labels_cb.setToolTip(
            'preserve existing labels while painting')
        preserve_labels_cb.stateChanged.connect(self.change_preserve_labels)
        self.preserveLabelsCheckBox = preserve_labels_cb
        self._on_preserve_labels_change()

        # shuffle colormap button
        self.colormapUpdate = QtModePushButton(
            None,
            'shuffle',
            slot=self.changeColor,
            tooltip='shuffle colors',
        )

        self.panzoom_button = QtModeRadioButton(
            layer,
            'zoom',
            Mode.PAN_ZOOM,
            tooltip='Pan/zoom mode (Space)',
            checked=True,
        )
        self.pick_button = QtModeRadioButton(layer,
                                             'picker',
                                             Mode.PICK,
                                             tooltip='Pick mode')
        self.paint_button = QtModeRadioButton(layer,
                                              'paint',
                                              Mode.PAINT,
                                              tooltip='Paint mode')
        btn = 'Cmd' if sys.platform == 'darwin' else 'Ctrl'
        self.fill_button = QtModeRadioButton(layer,
                                             'fill',
                                             Mode.FILL,
                                             tooltip=f'Fill mode ({btn})')
        self.erase_button = QtModeRadioButton(layer,
                                              'erase',
                                              Mode.ERASE,
                                              tooltip='Erase mode (Alt)')

        self.button_group = QButtonGroup(self)
        self.button_group.addButton(self.panzoom_button)
        self.button_group.addButton(self.paint_button)
        self.button_group.addButton(self.pick_button)
        self.button_group.addButton(self.fill_button)
        self.button_group.addButton(self.erase_button)
        self._on_editable_change()

        button_row = QHBoxLayout()
        button_row.addStretch(1)
        button_row.addWidget(self.colormapUpdate)
        button_row.addWidget(self.erase_button)
        button_row.addWidget(self.fill_button)
        button_row.addWidget(self.paint_button)
        button_row.addWidget(self.pick_button)
        button_row.addWidget(self.panzoom_button)
        button_row.setSpacing(4)
        button_row.setContentsMargins(0, 0, 0, 5)

        color_layout = QHBoxLayout()
        color_layout.addWidget(QtColorBox(layer))
        color_layout.addWidget(self.selectionSpinBox)

        # grid_layout created in QtLayerControls
        # addWidget(widget, row, column, [row_span, column_span])
        self.grid_layout.addLayout(button_row, 0, 0, 1, 2)
        self.grid_layout.addWidget(QLabel('label:'), 1, 0)
        self.grid_layout.addLayout(color_layout, 1, 1)
        self.grid_layout.addWidget(QLabel('opacity:'), 2, 0)
        self.grid_layout.addWidget(self.opacitySlider, 2, 1)
        self.grid_layout.addWidget(QLabel('brush size:'), 3, 0)
        self.grid_layout.addWidget(self.brushSizeSlider, 3, 1)
        self.grid_layout.addWidget(QLabel('blending:'), 4, 0)
        self.grid_layout.addWidget(self.blendComboBox, 4, 1)
        self.grid_layout.addWidget(QLabel('contiguous:'), 5, 0)
        self.grid_layout.addWidget(self.contigCheckBox, 5, 1)
        self.grid_layout.addWidget(QLabel('n-dim:'), 6, 0)
        self.grid_layout.addWidget(self.ndimCheckBox, 6, 1)
        self.grid_layout.addWidget(QLabel('preserve labels:'), 7, 0)
        self.grid_layout.addWidget(self.preserveLabelsCheckBox, 7, 1)
        self.grid_layout.setRowStretch(8, 1)
        self.grid_layout.setColumnStretch(1, 1)
        self.grid_layout.setSpacing(4)

    def mouseMoveEvent(self, event):
        """On mouse move, set layer status equal to the current selected mode.

        Available mode options are: PAN_ZOOM, PICKER, PAINT, ERASE or FILL

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.
        """
        self.layer.status = str(self.layer.mode)

    def _on_mode_change(self, event):
        """Receive layer model mode change event and update checkbox ticks.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent
            Event from the Qt context.

        Raises
        ------
        ValueError
            Raise error if event.mode is not PAN_ZOOM, PICK, PAINT, ERASE, or
            FILL
        """
        mode = event.mode
        if mode == Mode.PAN_ZOOM:
            self.panzoom_button.setChecked(True)
        elif mode == Mode.PICK:
            self.pick_button.setChecked(True)
        elif mode == Mode.PAINT:
            self.paint_button.setChecked(True)
        elif mode == Mode.FILL:
            self.fill_button.setChecked(True)
        elif mode == Mode.ERASE:
            self.erase_button.setChecked(True)
        else:
            raise ValueError("Mode not recognized")

    def changeColor(self):
        """Change colormap of the label layer."""
        self.layer.new_colormap()

    def changeSelection(self, value):
        """Change currently selected label.

        Parameters
        ----------
        value : int
            Index of label to select.
        """
        self.layer.selected_label = value
        self.selectionSpinBox.clearFocus()
        self.setFocus()

    def changeSize(self, value):
        """Change paint brush size.

        Parameters
        ----------
        value : float
            Size of the paint brush.
        """
        self.layer.brush_size = value

    def change_contig(self, state):
        """Toggle contiguous state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if labels are contiguous.
        """
        if state == Qt.Checked:
            self.layer.contiguous = True
        else:
            self.layer.contiguous = False

    def change_ndim(self, state):
        """Toggle n-dimensional state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if label layer is n-dimensional.
        """
        if state == Qt.Checked:
            self.layer.n_dimensional = True
        else:
            self.layer.n_dimensional = False

    def change_preserve_labels(self, state):
        """Toggle preserve_labels state of label layer.

        Parameters
        ----------
        state : QCheckBox
            Checkbox indicating if overwriting label is enabled.
        """
        if state == Qt.Checked:
            self.layer.preserve_labels = True
        else:
            self.layer.preserve_labels = False

    def _on_selection_change(self, event=None):
        """Receive layer model label selection change event and update spinbox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        with self.layer.events.selected_label.blocker():
            value = self.layer.selected_label
            self.selectionSpinBox.setValue(int(value))

    def _on_brush_size_change(self, event=None):
        """Receive layer model brush size change event and update the slider.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        with self.layer.events.brush_size.blocker():
            value = self.layer.brush_size
            value = np.clip(int(value), 1, 40)
            self.brushSizeSlider.setValue(value)

    def _on_n_dim_change(self, event=None):
        """Receive layer model n-dim mode change event and update the checkbox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        with self.layer.events.n_dimensional.blocker():
            self.ndimCheckBox.setChecked(self.layer.n_dimensional)

    def _on_contig_change(self, event=None):
        """Receive layer model contiguous change event and update the checkbox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        with self.layer.events.contiguous.blocker():
            self.contigCheckBox.setChecked(self.layer.contiguous)

    def _on_preserve_labels_change(self, event=None):
        """Receive layer model preserve_labels event and update the checkbox.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        with self.layer.events.preserve_labels.blocker():
            self.preserveLabelsCheckBox.setChecked(self.layer.preserve_labels)

    def _on_editable_change(self, event=None):
        """Receive layer model editable change event & enable/disable buttons.

        Parameters
        ----------
        event : qtpy.QtCore.QEvent, optional.
            Event from the Qt context.
        """
        disable_with_opacity(
            self,
            ['pick_button', 'paint_button', 'fill_button'],
            self.layer.editable,
        )
コード例 #31
0
class ProgressView(QWidget):
    """
    :type batch_manager: CalculationManager
    """
    def __init__(self, parent, batch_manager):
        QWidget.__init__(self, parent)
        self.calculation_manager = batch_manager
        self.whole_progress = QProgressBar(self)
        self.whole_progress.setMinimum(0)
        self.whole_progress.setMaximum(1)
        self.whole_progress.setFormat("%v of %m")
        self.whole_progress.setTextVisible(True)
        self.part_progress = QProgressBar(self)
        self.part_progress.setMinimum(0)
        self.part_progress.setMaximum(1)
        self.part_progress.setFormat("%v of %m")
        self.whole_label = QLabel("All batch progress:", self)
        self.part_label = QLabel("Single batch progress:", self)
        self.logs = ExceptionList(self)
        self.logs.setToolTip("Logs")
        self.task_que = QListWidget()
        self.process_num_timer = QTimer()
        self.process_num_timer.setInterval(1000)
        self.process_num_timer.setSingleShot(True)
        self.process_num_timer.timeout.connect(self.change_number_of_workers)
        self.number_of_process = QSpinBox(self)
        self.number_of_process.setRange(1, multiprocessing.cpu_count())
        self.number_of_process.setValue(1)
        self.number_of_process.setToolTip(
            "Number of process used in batch calculation")
        self.number_of_process.valueChanged.connect(
            self.process_num_timer_start)
        layout = QGridLayout()
        layout.addWidget(self.whole_label, 0, 0, Qt.AlignRight)
        layout.addWidget(self.whole_progress, 0, 1, 1, 2)
        layout.addWidget(self.part_label, 1, 0, Qt.AlignRight)
        layout.addWidget(self.part_progress, 1, 1, 1, 2)
        lab = QLabel("Number of process:")
        lab.setToolTip("Number of process used in batch calculation")
        layout.addWidget(lab, 2, 0)
        layout.addWidget(self.number_of_process, 2, 1)
        layout.addWidget(self.logs, 3, 0, 1, 3)
        layout.addWidget(self.task_que, 0, 4, 0, 1)
        layout.setColumnMinimumWidth(2, 10)
        layout.setColumnStretch(2, 1)
        self.setLayout(layout)
        self.preview_timer = QTimer()
        self.preview_timer.setInterval(1000)
        self.preview_timer.timeout.connect(self.update_info)

    def new_task(self):
        self.whole_progress.setMaximum(
            self.calculation_manager.calculation_size)
        if not self.preview_timer.isActive():
            self.update_info()
            self.preview_timer.start()

    def update_info(self):
        res = self.calculation_manager.get_results()
        for el in res.errors:
            if el[0]:
                QListWidgetItem(el[0], self.logs)
            ExceptionListItem(el[1], self.logs)
            if (state_store.report_errors and parsed_version.is_devrelease
                    and not isinstance(el[1][0], SegmentationLimitException)
                    and isinstance(el[1][1], tuple)):
                with sentry_sdk.push_scope() as scope:
                    scope.set_tag("auto_report", "true")
                    sentry_sdk.capture_event(el[1][1][0])
        self.whole_progress.setValue(res.global_counter)
        working_search = True
        for i, (progress, total) in enumerate(res.jobs_status):
            if working_search and progress != total:
                self.part_progress.setMaximum(total)
                self.part_progress.setValue(progress)
                working_search = False
            if i < self.task_que.count():
                item = self.task_que.item(i)
                item.setText("Task {} ({}/{})".format(i, progress, total))
            else:
                self.task_que.addItem("Task {} ({}/{})".format(
                    i, progress, total))
        if not self.calculation_manager.has_work:
            print(
                "[ProgressView.update_info]",
                self.calculation_manager.has_work,
                self.calculation_manager.batch_manager.has_work,
                self.calculation_manager.writer.writing_finished(),
            )
            self.part_progress.setValue(self.part_progress.maximum())
            self.preview_timer.stop()
            logging.info("Progress stop")

    def process_num_timer_start(self):
        self.process_num_timer.start()

    def update_progress(self, total_progress, part_progress):
        self.whole_progress.setValue(total_progress)
        self.part_progress.setValue(part_progress)

    def set_total_size(self, size):
        self.whole_progress.setMaximum(size)

    def set_part_size(self, size):
        self.part_progress.setMaximum(size)

    def change_number_of_workers(self):
        self.calculation_manager.set_number_of_workers(
            self.number_of_process.value())
コード例 #32
0
class MaskWidget(QWidget):
    values_changed = Signal()

    def __init__(self, settings: ImageSettings, parent=None):
        super().__init__(parent)
        self.setContentsMargins(0, 0, 0, 0)
        self.settings = settings
        self.dilate_radius = QSpinBox()
        self.dilate_radius.setRange(-100, 100)
        # self.dilate_radius.setButtonSymbols(QAbstractSpinBox.NoButtons)
        self.dilate_radius.setSingleStep(1)
        self.dilate_radius.setDisabled(True)
        self.dilate_dim = QEnumComboBox(enum_class=RadiusType)
        self.dilate_dim.setToolTip("With minus radius mask will be eroded")
        # noinspection PyUnresolvedReferences
        self.dilate_dim.currentIndexChanged.connect(
            partial(off_widget, self.dilate_radius, self.dilate_dim))

        self.radius_information = QLabel()

        # noinspection PyUnresolvedReferences
        self.dilate_radius.valueChanged.connect(self.dilate_change)
        # noinspection PyUnresolvedReferences
        self.dilate_dim.currentIndexChanged.connect(self.dilate_change)

        self.fill_holes = QEnumComboBox(enum_class=RadiusType)
        self.max_hole_size = QSpinBox()
        self.max_hole_size.setRange(-1, 10000)
        self.max_hole_size.setValue(-1)
        self.max_hole_size.setSingleStep(100)
        self.max_hole_size.setDisabled(True)
        self.max_hole_size.setToolTip(
            "Maximum size of holes to be closed. -1 means that all holes will be closed"
        )
        # noinspection PyUnresolvedReferences
        self.fill_holes.currentIndexChanged.connect(
            partial(off_widget, self.max_hole_size, self.fill_holes))

        self.save_components = QCheckBox()
        self.clip_to_mask = QCheckBox()
        self.reversed_check = QCheckBox()

        # noinspection PyUnresolvedReferences
        self.dilate_radius.valueChanged.connect(self.values_changed.emit)
        # noinspection PyUnresolvedReferences
        self.dilate_dim.currentIndexChanged.connect(self.values_changed.emit)
        # noinspection PyUnresolvedReferences
        self.fill_holes.currentIndexChanged.connect(self.values_changed.emit)
        # noinspection PyUnresolvedReferences
        self.max_hole_size.valueChanged.connect(self.values_changed.emit)
        self.save_components.stateChanged.connect(self.values_changed.emit)
        self.clip_to_mask.stateChanged.connect(self.values_changed.emit)
        self.reversed_check.stateChanged.connect(self.values_changed.emit)

        layout = QVBoxLayout()
        layout1 = QHBoxLayout()
        layout1.addWidget(QLabel("Dilate mask:"))
        layout1.addWidget(self.dilate_dim)
        layout1.addWidget(QLabel("radius (in pix):"))
        layout1.addWidget(self.dilate_radius)
        layout.addLayout(layout1)
        layout2 = QHBoxLayout()
        layout2.addWidget(QLabel("Fill holes:"))
        layout2.addWidget(self.fill_holes)
        layout2.addWidget(QLabel("Max size:"))
        layout2.addWidget(self.max_hole_size)
        layout.addLayout(layout2)
        layout3 = QHBoxLayout()
        comp_lab = QLabel("Save components:")
        comp_lab.setToolTip(
            "save components information in mask. Dilation, "
            "holes filing will be done separately for each component")
        self.save_components.setToolTip(comp_lab.toolTip())
        layout3.addWidget(comp_lab)
        layout3.addWidget(self.save_components)
        layout3.addStretch()
        clip_mask = QLabel("Clip to previous mask:")
        clip_mask.setToolTip("Useful dilated new mask")
        layout3.addWidget(clip_mask)
        layout3.addWidget(self.clip_to_mask)
        layout.addLayout(layout3)
        layout4 = QHBoxLayout()
        layout4.addWidget(QLabel("Reversed mask:"))
        layout4.addWidget(self.reversed_check)
        layout4.addStretch(1)
        layout.addLayout(layout4)
        self.setLayout(layout)
        self.dilate_change()

    def get_dilate_radius(self):
        radius = calculate_operation_radius(self.dilate_radius.value(),
                                            self.settings.image_spacing,
                                            self.dilate_dim.currentEnum())
        if isinstance(radius, (list, tuple)):
            return [int(x + 0.5) for x in radius]
        return int(radius)

    def dilate_change(self):
        if self.dilate_radius.value() == 0 or self.dilate_dim.currentEnum(
        ) == RadiusType.NO:
            self.radius_information.setText("Dilation radius: 0")
        else:
            dilate_radius = self.get_dilate_radius()
            if isinstance(dilate_radius, list):
                self.radius_information.setText(
                    f"Dilation radius: {dilate_radius[::-1]}")
            else:
                self.radius_information.setText(
                    f"Dilation radius: {dilate_radius}")

    def get_mask_property(self):
        return MaskProperty(
            dilate=self.dilate_dim.currentEnum()
            if self.dilate_radius.value() != 0 else RadiusType.NO,
            dilate_radius=self.dilate_radius.value()
            if self.dilate_dim.currentEnum() != RadiusType.NO else 0,
            fill_holes=self.fill_holes.currentEnum()
            if self.max_hole_size.value() != 0 else RadiusType.NO,
            max_holes_size=self.max_hole_size.value()
            if self.fill_holes.currentEnum() != RadiusType.NO else 0,
            save_components=self.save_components.isChecked(),
            clip_to_mask=self.clip_to_mask.isChecked(),
            reversed_mask=self.reversed_check.isChecked(),
        )

    def set_mask_property(self, prop: MaskProperty):
        self.dilate_dim.setCurrentEnum(prop.dilate)
        self.dilate_radius.setValue(prop.dilate_radius)
        self.fill_holes.setCurrentEnum(prop.fill_holes)
        self.max_hole_size.setValue(prop.max_holes_size)
        self.save_components.setChecked(prop.save_components)
        self.clip_to_mask.setChecked(prop.clip_to_mask)
        self.reversed_check.setChecked(prop.reversed_mask)
コード例 #33
0
class CurveSettingsDisplay(Display):
    def __init__(self, main_display, pv_name, parent=None):
        """
        Create all the widgets for the curve appearance settings.

        Parameters
        ----------
        main_display : TimeChartDisplay
            The main display window
        pv_name: str
            The name of the PV the current curve is being plotted for
        parent : QWidget
            The parent widget, if applicable
        """
        super(CurveSettingsDisplay, self).__init__(parent=parent)
        self.main_layout = QFormLayout()
        self.main_display = main_display

        self.chart = self.main_display.chart
        self.pv_name = pv_name
        self.channel_map = self.main_display.channel_map
        self.app = self.main_display.app

        self.curve_original_color = None
        self.curve_color_lbl = QLabel("Curve Color ")
        self.curve_color_btn = QPushButton()
        self.curve_color_btn.setMaximumWidth(20)
        self.curve_color_btn.clicked.connect(
            self.handle_curve_color_button_clicked)

        self.symbol_lbl = QLabel("Symbol")
        self.symbol_cmb = QComboBox()
        self.symbol_size_lbl = QLabel("Symbol Size")
        self.symbol_size_spin = QSpinBox()

        self.line_style_lbl = QLabel("Line Style")
        self.line_style_cmb = QComboBox()
        self.line_width_lbl = QLabel("Line Width")
        self.line_width_spin = QSpinBox()

        self.set_defaults_btn = QPushButton("Reset")
        self.set_defaults_btn.clicked.connect(self.handle_reset_button_clicked)

        self.close_dialog_btn = QPushButton("Close")
        self.close_dialog_btn.clicked.connect(self.handle_close_button_clicked)

        self.setWindowTitle(self.pv_name.split("://")[1])
        self.setFixedSize(QSize(300, 200))
        self.setWindowModality(Qt.ApplicationModal)

        self.setup_ui()

    def ui_filepath(self):
        """
        The path to the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def ui_filename(self):
        """
        The name of the UI file created by Qt Designer, if applicable.
        """
        # No UI file is being used
        return None

    def setup_ui(self):
        """
        Initialize the widgets and layouts.
        """
        # Populate the values
        for k, _ in BasePlotCurveItem.symbols.items():
            self.symbol_cmb.addItem(k)
        self.symbol_size_spin.setRange(1, 10)

        for k, _ in BasePlotCurveItem.lines.items():
            self.line_style_cmb.addItem(k)
        self.line_width_spin.setRange(1, 5)

        # Set the widget values to the current settings of the current curve
        self.set_widgets_to_current_curve_settings()

        # Connect to slots to handle signal events
        self.symbol_cmb.currentIndexChanged.connect(
            self.handle_symbol_index_changed)
        self.symbol_size_spin.valueChanged.connect(
            self.handle_symbol_size_changed)

        self.line_style_cmb.currentIndexChanged.connect(
            self.handle_line_style_index_changed)
        self.line_width_spin.valueChanged.connect(
            self.handle_line_width_changed)

        # Add widgets to the form layout
        self.main_layout.setSpacing(10)
        self.main_layout.addRow(self.curve_color_lbl, self.curve_color_btn)
        self.main_layout.addRow(self.symbol_lbl, self.symbol_cmb)
        self.main_layout.addRow(self.symbol_size_lbl, self.symbol_size_spin)
        self.main_layout.addRow(self.line_style_lbl, self.line_style_cmb)
        self.main_layout.addRow(self.line_width_lbl, self.line_width_spin)
        self.main_layout.addRow(self.set_defaults_btn, self.close_dialog_btn)

        # Add the form layout to the main layout of this dialog
        self.setLayout(self.main_layout)

    def set_widgets_to_current_curve_settings(self):
        """
        Make the dialog widgets display the current appearance settings of the current curve.
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            self.curve_color_btn.setStyleSheet("background-color: " +
                                               curve.color.name())

            self.set_combo_box(self.symbol_cmb, BasePlotCurveItem.symbols,
                               curve.symbol)
            self.set_combo_box(self.line_style_cmb, BasePlotCurveItem.lines,
                               curve.lineStyle)

            self.symbol_size_spin.setValue(curve.symbolSize)
            self.line_width_spin.setValue(curve.lineWidth)

    def set_combo_box(self, combo_box, reference_dict, curve_setting_value):
        """
        Reverse look up for a dictionary key using a dictionary value, and then set that value to a QComboBox widget.

        Parameters
        ----------
        combo_box : QComboBox
            The combo box to set the current value for
        reference_dict : dict
            The reference dict to find the key from a value to set the combo box
        curve_setting_value : str
            The setting value to look for from the reference_dict
        """
        for k, v in reference_dict.items():
            if curve_setting_value == v:
                combo_box.setCurrentText(k)
                break

    def handle_curve_color_button_clicked(self):
        selected_color = QColorDialog.getColor()
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            self.curve_original_color = curve.color
            curve.color = selected_color
            self.curve_color_btn.setStyleSheet("background-color: " +
                                               curve.color.name())

            self.chart.refreshCurve(curve)
            self.channel_map[self.pv_name] = curve

    def handle_symbol_index_changed(self, selected_index):
        """
        Handle the change in the curve's symbol from a combo box.

        Parameters
        ----------
        selected_index : int
            The currently selected index from the symbol combo box
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            curve.symbol = BasePlotCurveItem.symbols[self.symbol_cmb.itemText(
                selected_index)]
            self.chart.refreshCurve(curve)
            self.channel_map[self.pv_name] = curve

    def handle_symbol_size_changed(self, new_size):
        """
        Handle the symbol size value change from the symbol size spinner.

        Parameters
        ----------
        new_size : int
            The new symbol size set by the user.
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            curve.symbolSize = new_size
            self.chart.refreshCurve(curve)
            self.channel_map[self.pv_name] = curve

    def handle_line_width_changed(self, new_width):
        """
        Handle the symbol size value change from the line width spinner.

        Parameters
        ----------
        new_width: int
            The new line width set by the user.
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            curve.lineWidth = new_width
            self.chart.refreshCurve(curve)
            self.channel_map[self.pv_name] = curve

    def handle_line_style_index_changed(self, selected_index):
        """
        Handle the change in the curve's line style from a combo box.

        Parameters
        ----------
        selected_index : int
            The currently selected index from the line style combo box
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            curve.lineStyle = BasePlotCurveItem.lines[
                self.line_style_cmb.itemText(selected_index)]
            self.chart.refreshCurve(curve)
            self.channel_map[self.pv_name] = curve

    def handle_reset_button_clicked(self):
        """
        Handle the click of the Reset button. This will set all the dialog widgets to the default curve appearance
        settings.
        """
        curve = self.chart.findCurve(self.pv_name)
        if curve:
            if self.curve_original_color:
                curve.color = self.curve_original_color
                self.curve_color_btn.setStyleSheet("background-color: " +
                                                   curve.color.name())

            self.symbol_cmb.setCurrentIndex(0)
            self.symbol_size_spin.setValue(10)

            self.line_style_cmb.setCurrentIndex(1)
            self.line_width_spin.setValue(1)

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

    def handle_close_button_clicked(self):
        """
        Close the dialog when the Close button is clicked.
        """
        self.close()

        curve = self.chart.findCurve(self.pv_name)
        if curve:
            # Update the widget checkbox text to the current curve color
            widget = self.main_display.findChild(QGroupBox,
                                                 self.pv_name + "_grb")
            chb = widget.findChild(QCheckBox, self.pv_name + "_chb")
            lbl = widget.findChild(QLabel, self.pv_name + "_lbl")
            widget = [chb, lbl]
            for w in widget:
                palette = w.palette()
                palette.setColor(QPalette.Active, QPalette.WindowText,
                                 curve.color)
                w.setPalette(palette)
コード例 #34
0
ファイル: lspmanager.py プロジェクト: vasulakkaraju/spyder
class LSPServerEditor(QDialog):
    DEFAULT_HOST = '127.0.0.1'
    DEFAULT_PORT = 2084
    DEFAULT_CMD = ''
    DEFAULT_ARGS = ''
    DEFAULT_CONFIGURATION = '{}'
    DEFAULT_EXTERNAL = False
    HOST_REGEX = re.compile(r'^\w+([.]\w+)*$')
    NON_EMPTY_REGEX = re.compile(r'^\S+$')
    JSON_VALID = _('JSON valid')
    JSON_INVALID = _('JSON invalid')

    def __init__(self, parent, language=None, cmd='', host='127.0.0.1',
                 port=2084, args='', external=False, configurations={},
                 **kwargs):
        super(LSPServerEditor, self).__init__(parent)
        self.parent = parent
        self.external = external
        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        self.button_ok = bbox.button(QDialogButtonBox.Ok)
        self.button_cancel = bbox.button(QDialogButtonBox.Cancel)
        self.button_ok.setEnabled(False)

        description = _('To create a new configuration, '
                        'you need to select a programming '
                        'language, along with a executable '
                        'name for the server to execute '
                        '(If the instance is local), '
                        'and the host and port. Finally, '
                        'you need to provide the '
                        'arguments that the server accepts. '
                        'The placeholders <tt>%(host)s</tt> and '
                        '<tt>%(port)s</tt> refer to the host '
                        'and the port, respectively.')
        server_settings_description = QLabel(description)
        server_settings_description.setWordWrap(True)

        lang_label = QLabel(_('Language:'))
        self.lang_cb = QComboBox(self)
        self.lang_cb.setToolTip(_('Programming language provided '
                                  'by the LSP server'))
        self.lang_cb.addItem(_('Select a language'))
        self.lang_cb.addItems(LSP_LANGUAGES)

        if language is not None:
            idx = LSP_LANGUAGES.index(language)
            self.lang_cb.setCurrentIndex(idx + 1)
            self.button_ok.setEnabled(True)

        host_label = QLabel(_('Host:'))
        self.host_input = QLineEdit(self)
        self.host_input.setToolTip(_('Name of the host that will provide '
                                     'access to the server'))
        self.host_input.setText(host)
        self.host_input.textChanged.connect(lambda x: self.validate())

        port_label = QLabel(_('Port:'))
        self.port_spinner = QSpinBox(self)
        self.port_spinner.setToolTip(_('TCP port number of the server'))
        self.port_spinner.setMinimum(1)
        self.port_spinner.setMaximum(60000)
        self.port_spinner.setValue(port)

        cmd_label = QLabel(_('Command to execute:'))
        self.cmd_input = QLineEdit(self)
        self.cmd_input.setToolTip(_('Command used to start the '
                                    'LSP server locally'))
        self.cmd_input.setText(cmd)

        if not external:
            self.cmd_input.textChanged.connect(lambda x: self.validate())

        args_label = QLabel(_('Server arguments:'))
        self.args_input = QLineEdit(self)
        self.args_input.setToolTip(_('Additional arguments required to '
                                     'start the server'))
        self.args_input.setText(args)

        conf_label = QLabel(_('LSP Server Configurations:'))
        self.conf_input = CodeEditor(None)
        self.conf_input.textChanged.connect(self.validate)
        color_scheme = CONF.get('color_schemes', 'selected')
        self.conf_input.setup_editor(
            language='JSON',
            color_scheme=color_scheme,
            wrap=False,
            edge_line=True,
            highlight_current_line=True,
            highlight_current_cell=True,
            occurrence_highlighting=True,
            auto_unindent=True,
            font=get_font(),
            filename='config.json')
        self.conf_input.setToolTip(_('Additional LSP server configurations '
                                     'set at runtime. JSON required'))
        conf_text = '{}'
        try:
            conf_text = json.dumps(configurations, indent=4, sort_keys=True)
        except Exception:
            pass
        self.conf_input.set_text(conf_text)
        self.json_label = QLabel(self.JSON_VALID, self)

        self.external_cb = QCheckBox(_('External server'), self)
        self.external_cb.setToolTip(_('Check if the server runs '
                                      'on a remote location'))
        self.external_cb.setChecked(external)
        self.external_cb.stateChanged.connect(self.set_local_options)

        hlayout = QHBoxLayout()
        general_vlayout = QVBoxLayout()
        general_vlayout.addWidget(server_settings_description)

        vlayout = QVBoxLayout()
        lang_layout = QVBoxLayout()
        lang_layout.addWidget(lang_label)
        lang_layout.addWidget(self.lang_cb)

        # layout2 = QHBoxLayout()
        # layout2.addLayout(lang_layout)
        lang_layout.addWidget(self.external_cb)
        vlayout.addLayout(lang_layout)

        host_layout = QVBoxLayout()
        host_layout.addWidget(host_label)
        host_layout.addWidget(self.host_input)

        port_layout = QVBoxLayout()
        port_layout.addWidget(port_label)
        port_layout.addWidget(self.port_spinner)

        conn_info_layout = QHBoxLayout()
        conn_info_layout.addLayout(host_layout)
        conn_info_layout.addLayout(port_layout)
        vlayout.addLayout(conn_info_layout)

        cmd_layout = QVBoxLayout()
        cmd_layout.addWidget(cmd_label)
        cmd_layout.addWidget(self.cmd_input)
        vlayout.addLayout(cmd_layout)

        args_layout = QVBoxLayout()
        args_layout.addWidget(args_label)
        args_layout.addWidget(self.args_input)
        vlayout.addLayout(args_layout)

        conf_layout = QVBoxLayout()
        conf_layout.addWidget(conf_label)
        conf_layout.addWidget(self.conf_input)
        conf_layout.addWidget(self.json_label)

        hlayout.addLayout(vlayout)
        hlayout.addLayout(conf_layout)
        general_vlayout.addLayout(hlayout)

        general_vlayout.addWidget(bbox)
        self.setLayout(general_vlayout)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        self.lang_cb.currentIndexChanged.connect(
            self.lang_selection_changed)
        self.form_status(False)
        if language is not None:
            self.form_status(True)
            self.validate()

    @Slot()
    def validate(self):
        host_text = self.host_input.text()
        cmd_text = self.cmd_input.text()
        if not self.HOST_REGEX.match(host_text):
            self.button_ok.setEnabled(False)
            self.host_input.setStyleSheet("QLineEdit{border: 1px solid red;}")
            self.host_input.setToolTip('Hostname must be valid')
            return
        else:
            self.host_input.setStyleSheet(
                "QLineEdit{border: 1px solid green;}")
            self.host_input.setToolTip('Hostname is valid')
            self.button_ok.setEnabled(True)

        if not self.external:
            if not self.NON_EMPTY_REGEX.match(cmd_text):
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Command must be non empty')
                return

            if find_program(cmd_text) is None:
                self.button_ok.setEnabled(False)
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid red;}")
                self.cmd_input.setToolTip('Program was not found '
                                          'on your system')
                return
            else:
                self.cmd_input.setStyleSheet(
                    "QLineEdit{border: 1px solid green;}")
                self.cmd_input.setToolTip('Program was found on your system')
                self.button_ok.setEnabled(True)
        try:
            json.loads(self.conf_input.toPlainText())
            try:
                self.json_label.setText(self.JSON_VALID)
            except:
                pass
        except (ValueError, json.decoder.JSONDecodeError):
            try:
                self.json_label.setText(self.JSON_INVALID)
                self.button_ok.setEnabled(False)
            except:
                pass

    def form_status(self, status):
        self.host_input.setEnabled(status)
        self.port_spinner.setEnabled(status)
        self.external_cb.setEnabled(status)
        self.cmd_input.setEnabled(status)
        self.args_input.setEnabled(status)
        self.conf_input.setEnabled(status)
        self.json_label.setVisible(status)

    @Slot()
    def lang_selection_changed(self):
        idx = self.lang_cb.currentIndex()
        if idx == 0:
            self.set_defaults()
            self.form_status(False)
            self.button_ok.setEnabled(False)
        else:
            server = self.parent.get_server_by_lang(LSP_LANGUAGES[idx - 1])
            self.form_status(True)
            if server is not None:
                self.host_input.setText(server.host)
                self.port_spinner.setValue(server.port)
                self.external_cb.setChecked(server.external)
                self.cmd_input.setText(server.cmd)
                self.args_input.setText(server.args)
                self.conf_input.set_text(json.dumps(server.configurations))
                self.json_label.setText(self.JSON_VALID)
                self.button_ok.setEnabled(True)
            else:
                self.set_defaults()

    def set_defaults(self):
        self.cmd_input.setStyleSheet('')
        self.host_input.setStyleSheet('')
        self.host_input.setText(self.DEFAULT_HOST)
        self.port_spinner.setValue(self.DEFAULT_PORT)
        self.external_cb.setChecked(self.DEFAULT_EXTERNAL)
        self.cmd_input.setText(self.DEFAULT_CMD)
        self.args_input.setText(self.DEFAULT_ARGS)
        self.conf_input.set_text(self.DEFAULT_CONFIGURATION)
        self.json_label.setText(self.JSON_VALID)

    @Slot(bool)
    @Slot(int)
    def set_local_options(self, enabled):
        self.external = enabled
        self.cmd_input.setEnabled(True)
        self.args_input.setEnabled(True)
        if enabled:
            self.cmd_input.setEnabled(False)
            self.cmd_input.setStyleSheet('')
            self.args_input.setEnabled(False)
        try:
            self.validate()
        except:
            pass

    def get_options(self):
        language_idx = self.lang_cb.currentIndex()
        language = LSP_LANGUAGES[language_idx - 1]
        host = self.host_input.text()
        port = int(self.port_spinner.value())
        external = self.external_cb.isChecked()
        args = self.args_input.text()
        cmd = self.cmd_input.text()
        configurations = json.loads(self.conf_input.toPlainText())
        server = LSPServer(language=language.lower(), cmd=cmd, args=args,
                           host=host, port=port, external=external,
                           configurations=configurations)
        return server
コード例 #35
0
class QuantityArrayEditor(QDialog):
    """Array Editor Dialog"""

    def __init__(self, parent=None):
        QDialog.__init__(self, parent)

        # Destroying the C++ object right after closing the dialog box,
        # otherwise it may be garbage-collected in another QThread
        # (e.g. the editor's analysis thread in Spyder), thus leading to
        # a segmentation fault on UNIX or an application crash on Windows
        self.setAttribute(Qt.WA_DeleteOnClose)

        self.data = None
        self.arraywidget = None
        self.stack = None
        self.layout = None
        # Values for 3d array editor
        self.dim_indexes = [{}, {}, {}]
        self.last_dim = 0  # Adjust this for changing the startup dimension
        self.unit = None

    def setup_and_check(self, data: _Quantity, title='', readonly=False, xlabels=None, ylabels=None):
        """
        Setup ArrayEditor:
        return False if data is not supported, True otherwise
        """
        self.data = data
        self.data.flags.writeable = True
        is_record_array = data.m.dtype.names is not None
        is_masked_array = isinstance(data.m, np.ma.MaskedArray)

        if data.m.ndim > 3:
            self.error("Arrays with more than 3 dimensions are not supported")
            return False
        if xlabels is not None and len(xlabels) != self.data.m.shape[1]:
            self.error("The 'xlabels' argument length do no match array column number")
            return False
        if ylabels is not None and len(ylabels) != self.data.m.shape[0]:
            self.error("The 'ylabels' argument length do no match array row number")
            return False
        if not is_record_array:
            dtn = data.m.dtype.name
            if dtn not in SUPPORTED_FORMATS and not dtn.startswith('str') and not dtn.startswith('unicode'):
                arr = "%s arrays" % data.m.dtype.name
                self.error("%s are currently not supported" % arr)
                return False

        self.layout = QGridLayout()
        self.setLayout(self.layout)
        # self.setWindowIcon(ima.icon('arredit'))
        if title:
            title = str(title) + " - " + "NumPy array" + str(data.u)
        else:
            title = "Array editor"
        if readonly:
            title += ' (' + 'read only' + ')'
        self.setWindowTitle(title)
        self.resize(600, 500)

        # Stack widget
        self.stack = QStackedWidget(self)
        if is_record_array:
            for name in data.dtype.names:
                self.stack.addWidget(QuantityArrayEditorWidget(self, data[name], readonly, xlabels, ylabels))
        elif is_masked_array:
            self.stack.addWidget(QuantityArrayEditorWidget(self, data, readonly, xlabels, ylabels))
            self.stack.addWidget(QuantityArrayEditorWidget(self, data.data, readonly, xlabels, ylabels))
            self.stack.addWidget(QuantityArrayEditorWidget(self, data.mask, readonly, xlabels, ylabels))
        elif data.ndim == 3:
            pass
        else:
            self.stack.addWidget(QuantityArrayEditorWidget(self, data, readonly, xlabels, ylabels))

        self.arraywidget = self.stack.currentWidget()
        self.stack.currentChanged.connect(self.current_widget_changed)
        self.layout.addWidget(self.stack, 1, 0)

        self.unitLabel = QLabel()
        self.unitLabel.setText(f'Unit: {data.u}')
        self.dimensionLabel = QLabel()
        self.dimensionLabel.setText(f'Dimension: {data.dimensionality}')

        self.layout.addWidget(self.unitLabel)
        self.layout.addWidget(self.dimensionLabel)

        # Buttons configuration
        btn_layout = QHBoxLayout()
        if is_record_array or is_masked_array or data.m.ndim == 3:
            if is_record_array:
                btn_layout.addWidget(QLabel("Record array fields:"))
                names = []
                for name in data.m.dtype.names:
                    field = data.m.dtype.fields[name]
                    text = name
                    if len(field) >= 3:
                        title = field[2]
                        if not is_text_string(title):
                            title = repr(title)
                        text += ' - ' + title
                    names.append(text)
            else:
                names = ['Masked data', 'Data', 'Mask']
            if data.m.ndim == 3:
                # QSpinBox
                self.index_spin = QSpinBox(self, keyboardTracking=False)
                self.index_spin.valueChanged.connect(self.change_active_widget)
                # QComboBox
                names = [str(i) for i in range(3)]
                ra_combo = QComboBox(self)
                ra_combo.addItems(names)
                ra_combo.currentIndexChanged.connect(self.current_dim_changed)
                # Adding the widgets to layout
                label = QLabel("Axis:")
                btn_layout.addWidget(label)
                btn_layout.addWidget(ra_combo)
                self.shape_label = QLabel()
                btn_layout.addWidget(self.shape_label)
                label = QLabel("Index:")
                btn_layout.addWidget(label)
                btn_layout.addWidget(self.index_spin)
                self.slicing_label = QLabel()
                btn_layout.addWidget(self.slicing_label)
                # set the widget to display when launched
                self.current_dim_changed(self.last_dim)
            else:
                ra_combo = QComboBox(self)
                ra_combo.currentIndexChanged.connect(self.stack.setCurrentIndex)
                ra_combo.addItems(names)
                btn_layout.addWidget(ra_combo)
            if is_masked_array:
                label = QLabel("<u>Warning</u>: changes are applied separately")
                label.setToolTip("For performance reasons, changes applied " \
                                 "to masked array won't be reflected in " \
                                 "array's data (and vice-versa).")
                btn_layout.addWidget(label)
            btn_layout.addStretch()

        bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        bbox.accepted.connect(self.accept)
        bbox.rejected.connect(self.reject)
        btn_layout.addWidget(bbox)
        self.layout.addLayout(btn_layout, 2, 0)
        self.setMinimumSize(400, 300)
        # Make the dialog act as a window
        self.setWindowFlags(Qt.Window)

        return True

    def current_widget_changed(self, index):
        self.arraywidget = self.stack.widget(index)

    def change_active_widget(self, index):
        """
        This is implemented for handling negative values in index for
        3d arrays, to give the same behavior as slicing
        """
        string_index = [':'] * 3
        string_index[self.last_dim] = '<font color=red>%i</font>'
        self.slicing_label.setText((r"Slicing: [" + ", ".join(string_index) + "]") % index)
        if index < 0:
            data_index = self.data.m.shape[self.last_dim] + index
        else:
            data_index = index
        slice_index = [slice(None)] * 3
        slice_index[self.last_dim] = data_index

        stack_index = self.dim_indexes[self.last_dim].get(data_index)
        if stack_index == None:
            stack_index = self.stack.count()
            self.stack.addWidget(QuantityArrayEditor(self, self.data.m[slice_index]))
            self.dim_indexes[self.last_dim][data_index] = stack_index
            self.stack.update()
        self.stack.setCurrentIndex(stack_index)

    def current_dim_changed(self, index):
        """
        This change the active axis the array editor is plotting over
        in 3D
        """
        self.last_dim = index
        string_size = ['%i'] * 3
        string_size[index] = '<font color=red>%i</font>'
        self.shape_label.setText(('Shape: (' + ', '.join(string_size) + ')    ') % self.data.shape)
        if self.index_spin.value() != 0:
            self.index_spin.setValue(0)
        else:
            # this is done since if the value is currently 0 it does not emit
            # currentIndexChanged(int)
            self.change_active_widget(0)
        self.index_spin.setRange(-self.data.shape[index], self.data.shape[index] - 1)

    @Slot()
    def accept(self):
        """Reimplement Qt method"""

        for index in range(self.stack.count()):
            self.stack.widget(index).accept_changes()

        QDialog.accept(self)

    def get_value(self):

        """Return modified array -- this is *not* a copy"""
        # It is import to avoid accessing Qt C++ object as it has probably
        # already been destroyed, due to the Qt.WA_DeleteOnClose attribute
        return self.data

    def error(self, message):
        """An error occured, closing the dialog box"""
        QMessageBox.critical(self, "Array editor", message)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.reject()

    @Slot()
    def reject(self):
        """Reimplement Qt method"""
        if self.arraywidget is not None:
            for index in range(self.stack.count()):
                self.stack.widget(index).reject_changes()
        QDialog.reject(self)
コード例 #36
0
ファイル: figurebrowser.py プロジェクト: impact27/spyder
class FigureBrowser(QWidget):
    """
    Widget to browse the figures that were sent by the kernel to the IPython
    console to be plotted inline.
    """
    sig_option_changed = Signal(str, object)
    sig_collapse = Signal()

    def __init__(self, parent=None, options_button=None, plugin_actions=[],
                 background_color=None):
        super(FigureBrowser, self).__init__(parent)

        self.shellwidget = None
        self.is_visible = True
        self.figviewer = None
        self.setup_in_progress = False
        self.background_color = background_color

        # Options :
        self.mute_inline_plotting = None
        self.show_plot_outline = None

        # Option actions :
        self.mute_inline_action = None
        self.show_plot_outline_action = None

        self.options_button = options_button
        self.plugin_actions = plugin_actions
        self.shortcuts = self.create_shortcuts()

    def setup(self, mute_inline_plotting=None, show_plot_outline=None):
        """Setup the figure browser with provided settings."""
        assert self.shellwidget is not None

        self.mute_inline_plotting = mute_inline_plotting
        self.show_plot_outline = show_plot_outline

        if self.figviewer is not None:
            self.mute_inline_action.setChecked(mute_inline_plotting)
            self.show_plot_outline_action.setChecked(show_plot_outline)
            return

        self.figviewer = FigureViewer(background_color=self.background_color)
        self.figviewer.setStyleSheet("FigureViewer{"
                                     "border: 1px solid lightgrey;"
                                     "border-top-width: 0px;"
                                     "border-bottom-width: 0px;"
                                     "border-left-width: 0px;"
                                     "}")
        self.thumbnails_sb = ThumbnailScrollBar(
            self.figviewer, background_color=self.background_color)

        # Option actions :
        self.setup_option_actions(mute_inline_plotting, show_plot_outline)

        # Create the layout :
        main_widget = QSplitter()
        main_widget.addWidget(self.figviewer)
        main_widget.addWidget(self.thumbnails_sb)
        main_widget.setFrameStyle(QScrollArea().frameStyle())

        self.tools_layout = QHBoxLayout()
        toolbar = self.setup_toolbar()
        for widget in toolbar:
            self.tools_layout.addWidget(widget)
        self.tools_layout.addStretch()
        self.setup_options_button()

        layout = create_plugin_layout(self.tools_layout, main_widget)
        self.setLayout(layout)

    def setup_toolbar(self):
        """Setup the toolbar"""
        savefig_btn = create_toolbutton(
                self, icon=ima.icon('filesave'),
                tip=_("Save Image As..."),
                triggered=self.save_figure)

        saveall_btn = create_toolbutton(
                self, icon=ima.icon('save_all'),
                tip=_("Save All Images..."),
                triggered=self.save_all_figures)

        copyfig_btn = create_toolbutton(
            self, icon=ima.icon('editcopy'),
            tip=_("Copy plot to clipboard as image (%s)" %
                  get_shortcut('plots', 'copy')),
            triggered=self.copy_figure)

        closefig_btn = create_toolbutton(
                self, icon=ima.icon('editclear'),
                tip=_("Remove image"),
                triggered=self.close_figure)

        closeall_btn = create_toolbutton(
                self, icon=ima.icon('filecloseall'),
                tip=_("Remove all images from the explorer"),
                triggered=self.close_all_figures)

        vsep1 = QFrame()
        vsep1.setFrameStyle(53)

        goback_btn = create_toolbutton(
                self, icon=ima.icon('ArrowBack'),
                tip=_("Previous Figure ({})".format(
                      get_shortcut('plots', 'previous figure'))),
                triggered=self.go_previous_thumbnail)

        gonext_btn = create_toolbutton(
                self, icon=ima.icon('ArrowForward'),
                tip=_("Next Figure ({})".format(
                      get_shortcut('plots', 'next figure'))),
                triggered=self.go_next_thumbnail)

        vsep2 = QFrame()
        vsep2.setFrameStyle(53)

        zoom_out_btn = create_toolbutton(
                self, icon=ima.icon('zoom_out'),
                tip=_("Zoom out (Ctrl + mouse-wheel-down)"),
                triggered=self.zoom_out)

        zoom_in_btn = create_toolbutton(
                self, icon=ima.icon('zoom_in'),
                tip=_("Zoom in (Ctrl + mouse-wheel-up)"),
                triggered=self.zoom_in)

        self.zoom_disp = QSpinBox()
        self.zoom_disp.setAlignment(Qt.AlignCenter)
        self.zoom_disp.setButtonSymbols(QSpinBox.NoButtons)
        self.zoom_disp.setReadOnly(True)
        self.zoom_disp.setSuffix(' %')
        self.zoom_disp.setRange(0, 9999)
        self.zoom_disp.setValue(100)
        self.figviewer.sig_zoom_changed.connect(self.zoom_disp.setValue)

        zoom_pan = QWidget()
        layout = QHBoxLayout(zoom_pan)
        layout.setSpacing(0)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(zoom_out_btn)
        layout.addWidget(zoom_in_btn)
        layout.addWidget(self.zoom_disp)

        return [savefig_btn, saveall_btn, copyfig_btn, closefig_btn,
                closeall_btn, vsep1, goback_btn, gonext_btn, vsep2, zoom_pan]

    def setup_option_actions(self, mute_inline_plotting, show_plot_outline):
        """Setup the actions to show in the cog menu."""
        self.setup_in_progress = True
        self.mute_inline_action = create_action(
            self, _("Mute inline plotting"),
            tip=_("Mute inline plotting in the ipython console."),
            toggled=lambda state:
            self.option_changed('mute_inline_plotting', state)
            )
        self.mute_inline_action.setChecked(mute_inline_plotting)

        self.show_plot_outline_action = create_action(
            self, _("Show plot outline"),
            tip=_("Show the plot outline."),
            toggled=self.show_fig_outline_in_viewer
            )
        self.show_plot_outline_action.setChecked(show_plot_outline)

        self.actions = [self.mute_inline_action, self.show_plot_outline_action]
        self.setup_in_progress = False

    def setup_options_button(self):
        """Add the cog menu button to the toolbar."""
        if not self.options_button:
            # When the FigureBowser widget is instatiated outside of the
            # plugin (for testing purpose for instance), we need to create
            # the options_button and set its menu.
            self.options_button = create_toolbutton(
                self, text=_('Options'), icon=ima.icon('tooloptions'))

            actions = self.actions + [MENU_SEPARATOR] + self.plugin_actions
            self.options_menu = QMenu(self)
            add_actions(self.options_menu, actions)
            self.options_button.setMenu(self.options_menu)

        if self.tools_layout.itemAt(self.tools_layout.count() - 1) is None:
            self.tools_layout.insertWidget(
                self.tools_layout.count() - 1, self.options_button)
        else:
            self.tools_layout.addWidget(self.options_button)

    def create_shortcuts(self):
        """Create shortcuts for this widget."""
        # Configurable
        copyfig = config_shortcut(self.copy_figure, context='plots',
                                  name='copy', parent=self)
        prevfig = config_shortcut(self.go_previous_thumbnail, context='plots',
                                  name='previous figure', parent=self)
        nextfig = config_shortcut(self.go_next_thumbnail, context='plots',
                                  name='next figure', parent=self)

        return [copyfig, prevfig, nextfig]

    def get_shortcut_data(self):
        """
        Return shortcut data, a list of tuples (shortcut, text, default).

        shortcut (QShortcut or QAction instance)
        text (string): action/shortcut description
        default (string): default key sequence
        """
        return [sc.data for sc in self.shortcuts]

    def option_changed(self, option, value):
        """Handle when the value of an option has changed"""
        setattr(self, to_text_string(option), value)
        self.shellwidget.set_namespace_view_settings()
        if self.setup_in_progress is False:
            self.sig_option_changed.emit(option, value)

    def show_fig_outline_in_viewer(self, state):
        """Draw a frame around the figure viewer if state is True."""
        if state is True:
            self.figviewer.figcanvas.setStyleSheet(
                    "FigureCanvas{border: 1px solid lightgrey;}")
        else:
            self.figviewer.figcanvas.setStyleSheet("FigureCanvas{}")
        self.option_changed('show_plot_outline', state)

    def set_shellwidget(self, shellwidget):
        """Bind the shellwidget instance to the figure browser"""
        self.shellwidget = shellwidget
        shellwidget.set_figurebrowser(self)
        shellwidget.sig_new_inline_figure.connect(self._handle_new_figure)

    def get_actions(self):
        """Get the actions of the widget."""
        return self.actions

    def _handle_new_figure(self, fig, fmt):
        """
        Handle when a new figure is sent to the IPython console by the
        kernel.
        """
        self.thumbnails_sb.add_thumbnail(fig, fmt)

    # ---- Toolbar Handlers
    def zoom_in(self):
        """Zoom the figure in by a single step in the figure viewer."""
        self.figviewer.zoom_in()

    def zoom_out(self):
        """Zoom the figure out by a single step in the figure viewer."""
        self.figviewer.zoom_out()

    def go_previous_thumbnail(self):
        """
        Select the thumbnail previous to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_previous_thumbnail()

    def go_next_thumbnail(self):
        """
        Select the thumbnail next to the currently selected one in the
        thumbnail scrollbar.
        """
        self.thumbnails_sb.go_next_thumbnail()

    def save_figure(self):
        """Save the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.save_current_figure_as()

    def save_all_figures(self):
        """Save all the figures in a selected directory."""
        return self.thumbnails_sb.save_all_figures_as()

    def close_figure(self):
        """Close the currently selected figure in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_current_thumbnail()

    def close_all_figures(self):
        """Close all the figures in the thumbnail scrollbar."""
        self.thumbnails_sb.remove_all_thumbnails()

    def copy_figure(self):
        """Copy figure from figviewer to clipboard."""
        if self.figviewer and self.figviewer.figcanvas.fig:
            self.figviewer.figcanvas.copy_figure()
コード例 #37
0
ファイル: imagerotation.py プロジェクト: hyperspy/hyperspyUI
class ImageRotationDialog(ExToolWindow):

    def __init__(self, signal, axes, parent, plugin):
        super(ImageRotationDialog, self).__init__(parent)
        self.ui = parent
        self.create_controls()
        self.accepted.connect(self.ok)
        self.rejected.connect(self.close_new)
        self.signal = signal
        self.plugin = plugin
        self.new_out = None
        self._connected_updates = False
        if isinstance(axes, str):
            axm = signal.signal.axes_manager
            if axes.startswith("nav"):
                axes = (axm._axes.index(axm.navigation_axes[0]),
                        axm._axes.index(axm.navigation_axes[1]))
            elif axes.startswith("sig"):
                axes = (axm._axes.index(axm.signal_axes[0]),
                        axm._axes.index(axm.signal_axes[1]))
        self.axes = axes
        self.setWindowTitle(tr("Rotate"))

        # TODO: TAG: Functionality check
        if not hasattr(signal.signal, 'events'):
            self.gbo_preview.setVisible(False)

        # TODO: Add dynamic rotation, e.g. one that rotates when source
        # signal's data_changed event triggers

    def connect(self):
        # TODO: Don't have to con/dis those in gbo
        self.opt_new.toggled.connect(self.close_new)
        self.num_angle.valueChanged.connect(self.update)
        self.chk_grid.toggled.connect(self.update)
        self.num_grid.valueChanged.connect(self.update)
        self.chk_reshape.toggled.connect(self.update)
        self.opt_new.toggled.connect(self.update)
        self.opt_replace.toggled.connect(self.update)

    def disconnect(self):
        self.num_angle.valueChanged.disconnect(self.update)
        self.chk_grid.toggled.disconnect(self.update)
        self.num_grid.valueChanged.disconnect(self.update)
        self.chk_reshape.toggled.disconnect(self.update)
        self.opt_new.toggled.disconnect(self.update)
        self.opt_replace.toggled.disconnect(self.update)

    def ok(self):
        # Draw figure if not already done
        # TODO: TAG: Functionality check
        if not hasattr(self.signal.signal, 'events') or \
                not self.gbo_preview.isChecked():
            self.update()
        angle = self.num_angle.value()
        reshape = self.chk_reshape.isChecked()
        self.plugin.record_code(
            r"<p>.rotate_signal({0}, reshape={1}, axes={2})".format(
                angle, reshape, self.axes))
        # Clean up event connections
        if self.new_out is not None:
            self.connect_update_plot(self.new_out.signal, disconnect=True)

    def close_new(self, value=False):
        if self.new_out is not None and not value:
            self.new_out.close()
            self.new_out = None
            self._connected_updates = False

    def set_preview(self, value):
        if not hasattr(self.signal.signal, 'events'):
            return
        if value:
            self.connect()
            self.update()
        else:
            self.disconnect()
            self.close_new()

    def _axes_in_nav(self):
        axm = self.signal.signal.axes_manager
        navidx = [axm._axes.index(ax) for ax in axm.navigation_axes]
        if self.axes[0] in navidx:
            return True
        return False

    def connect_update_plot(self, signal, disconnect=False):
        if self._connected_updates != disconnect:
            return  # Nothing to do, prevent double connections
        if self._axes_in_nav():
            f = signal._plot.navigator_plot.update
        else:
            f = signal._plot.signal_plot.update

        # TODO: TAG: Functionality check
        if hasattr(signal, 'events') and hasattr(
                signal.events, 'data_changed'):
            if disconnect:
                signal.events.data_changed.disconnect(f)
            else:
                signal.events.data_changed.connect(f, [])
        self._connected_updates = not disconnect

    def update(self):
        angle = self.num_angle.value()
        reshape = self.chk_reshape.isChecked()
        if self.opt_new.isChecked():
            if self.new_out is None:
                out = None
            else:
                out = self.new_out.signal
        elif self.opt_replace.isChecked():
            out = self.signal.signal
        else:
            return  # Indeterminate state, do nothing

        s = self.plugin.rotate_signal(angle, self.signal.signal, record=False,
                                      reshape=reshape, out=out, axes=self.axes)

        if out is None:
            s.metadata.General.title = self.signal.name + "[Rotated]"
            s.plot()
            self.connect_update_plot(s)
            if (self.gbo_preview.isChecked() and self.opt_new.isChecked() and
                                                         self.new_out is None):
                self.new_out = self.ui.lut_signalwrapper[s]
        else:
            s = out

        if self.chk_grid.isChecked() is True:
            pass    # TODO: Draw grid

    def create_controls(self):
        """
        Create UI controls.
        """
        vbox = QVBoxLayout()

        form = QFormLayout()
        self.num_angle = QDoubleSpinBox()
        self.num_angle.setValue(0.0)
        self.num_angle.setMinimum(-360)
        self.num_angle.setMaximum(360)
        form.addRow(tr("Angle:"), self.num_angle)
        vbox.addLayout(form)

        self.gbo_preview = QGroupBox(tr("Preview"))
        self.gbo_preview.setCheckable(True)
        self.gbo_preview.setChecked(False)
        gbo_vbox = QVBoxLayout()
        self.chk_grid = QCheckBox(tr("Grid"))
        self.chk_grid.setChecked(False)
        self.num_grid = QSpinBox()
        self.num_grid.setValue(4)
        self.num_grid.setMinimum(1)
        self.num_grid.setEnabled(False)
        self.chk_grid.toggled[bool].connect(self.num_grid.setEnabled)
        gbo_vbox.addWidget(self.chk_grid)
        gbo_vbox.addWidget(self.num_grid)
        self.gbo_preview.setLayout(gbo_vbox)
        vbox.addWidget(self.gbo_preview)

        self.gbo_preview.toggled[bool].connect(self.set_preview)

        self.gbo_output = QGroupBox(tr("Output"))
        self.opt_new = QRadioButton(tr("New signal"))
        self.opt_replace = QRadioButton(tr("In place"))
        self.opt_new.setChecked(True)
        gbo_vbox2 = QVBoxLayout()
        gbo_vbox2.addWidget(self.opt_new)
        gbo_vbox2.addWidget(self.opt_replace)
        self.gbo_output.setLayout(gbo_vbox2)
        vbox.addWidget(self.gbo_output)

        self.chk_reshape = QCheckBox(tr("Resize to fit"))
        self.chk_reshape.setChecked(False)
        vbox.addWidget(self.chk_reshape)

        self.btn_ok = QPushButton(tr("&OK"))
        self.btn_ok.setDefault(True)
        self.btn_ok.clicked.connect(self.accept)
        self.btn_cancel = QPushButton(tr("&Cancel"))
        self.btn_cancel.clicked.connect(self.reject)
        hbox = QHBoxLayout()
        hbox.addWidget(self.btn_ok)
        hbox.addWidget(self.btn_cancel)
        vbox.addLayout(hbox)

        vbox.addStretch(1)
        self.setLayout(vbox)