Beispiel #1
0
def connect_current_combo(client, prop, widget):
    """
    Connect widget.currentIndexChanged and client.prop

    client.prop should be a callback property
    """

    def _push_combo(value):
        # NOTE: we can't use findData here because if the data is not a
        # string, PySide will crash
        try:
            idx = _find_combo_data(widget, value)
        except ValueError:
            if value is None:
                idx = -1
            else:
                raise
        widget.setCurrentIndex(idx)

    def _pull_combo(idx):
        if idx == -1:
            setattr(client, prop, None)
        else:
            setattr(client, prop, widget.itemData(idx))

    add_callback(client, prop, _push_combo)
    widget.currentIndexChanged.connect(_pull_combo)
Beispiel #2
0
    def add_tool(self, tool):

        if isinstance(tool, DropdownTool) and len(tool.subtools) > 0:
            menu = QtWidgets.QMenu(self)
            for t in tool.subtools:
                action = self._make_action(t)
                menu.addAction(action)
        elif len(tool.menu_actions()) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in tool.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
        else:
            menu = None

        action = self._make_action(tool, menu=menu)

        self.addAction(action)

        self.actions[tool.tool_id] = action

        # Bind tool visibility to tool.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)

        add_callback(tool, 'enabled', toggle)

        self.tools[tool.tool_id] = tool

        return action
Beispiel #3
0
def connect_float_edit(client, prop, widget):
    """ Connect widget.setText and client.prop
    Also pretty-print the number

    client.prop should be a callback property
    """
    v = QtGui.QDoubleValidator(None)
    v.setDecimals(4)
    widget.setValidator(v)

    def update_prop():
        val = widget.text()
        try:
            setattr(client, prop, float(val))
        except ValueError:
            setattr(client, prop, 0)

    def update_widget(val):
        if val is None:
            val = 0.
        widget.setText(pretty_number(val))

    add_callback(client, prop, update_widget)
    widget.editingFinished.connect(update_prop)
    update_widget(getattr(client, prop))
Beispiel #4
0
    def _connect(self):
        ui = self.ui

        ui.monochrome.toggled.connect(self._update_rgb_console)
        ui.rgb_options.colors_changed.connect(self.update_window_title)

        # sync client and widget slices
        ui.slice.slice_changed.connect(
            lambda: setattr(self, 'slice', self.ui.slice.slice))
        update_ui_slice = lambda val: setattr(ui.slice, 'slice', val)
        add_callback(self.client, 'slice', update_ui_slice)
        add_callback(self.client, 'display_data', self.ui.slice.set_data)

        # sync window title to data/attribute
        add_callback(self.client, 'display_data',
                     nonpartial(self._display_data_changed))
        add_callback(self.client, 'display_attribute',
                     nonpartial(self._display_attribute_changed))
        add_callback(self.client, 'display_aspect',
                     nonpartial(self.client._update_aspect))

        # sync data/attribute combos with client properties
        connect_current_combo(self.client, 'display_data',
                              self.ui.displayDataCombo)
        connect_current_combo(self.client, 'display_attribute',
                              self.ui.attributeComboBox)
        connect_current_combo(self.client, 'display_aspect',
                              self.ui.aspectCombo)
Beispiel #5
0
    def _mouse_modes(self):

        axes = self.client.axes

        def apply_mode(mode):
            for roi_mode in roi_modes:
                if roi_mode != mode:
                    roi_mode._roi_tool.reset()
            self.apply_roi(mode.roi())

        rect = RectangleMode(axes, roi_callback=apply_mode)
        circ = CircleMode(axes, roi_callback=apply_mode)
        poly = PolyMode(axes, roi_callback=apply_mode)
        roi_modes = [rect, circ, poly]

        contrast = ContrastMode(axes, move_callback=self._set_norm)

        self._contrast = contrast

        # Get modes from tools
        tool_modes = []
        for tool in self._tools:
            tool_modes += tool._get_modes(axes)
            add_callback(self.client, 'display_data', tool._display_data_hook)

        return [rect, circ, poly, contrast] + tool_modes
Beispiel #6
0
    def _mouse_modes(self):

        axes = self.client.axes

        def apply_mode(mode):
            for roi_mode in roi_modes:
                if roi_mode != mode:
                    roi_mode._roi_tool.reset()
            self.apply_roi(mode.roi())

        rect = RectangleMode(axes, roi_callback=apply_mode)
        circ = CircleMode(axes, roi_callback=apply_mode)
        poly = PolyMode(axes, roi_callback=apply_mode)
        roi_modes = [rect, circ, poly]

        contrast = ContrastMode(axes, move_callback=self._set_norm)

        self._contrast = contrast

        # Get modes from tools
        tool_modes = []
        for tool in self._tools:
            tool_modes += tool._get_modes(axes)
            add_callback(self.client, 'display_data', tool._display_data_hook)

        return [rect, circ, poly, contrast] + tool_modes
Beispiel #7
0
    def _setup_grip(self):
        def _set_client_from_grip(value):
            """Update client.slice given grip value"""
            if not self.main.enabled:
                return

            slc = list(self.client.slice)
            # client.slice stored in pixel coords
            value = Extractor.world2pixel(self.data, self.profile_axis, value)
            slc[self.profile_axis] = value

            # prevent callback bouncing. Fixes #298
            with ignore_callback(self.grip, 'value'):
                self.client.slice = tuple(slc)

        def _set_grip_from_client(slc):
            """Update grip.value given client.slice"""
            if not self.main.enabled:
                return

            # grip.value is stored in world coordinates
            val = slc[self.profile_axis]
            val = Extractor.pixel2world(self.data, self.profile_axis, val)

            # If pix2world not monotonic, this can trigger infinite recursion.
            # Avoid by disabling callback loop
            # XXX better to specifically ignore _set_client_from_grip
            with ignore_callback(self.client, 'slice'):
                self.grip.value = val

        self.grip = self.main.profile.new_value_grip()

        add_callback(self.client, 'slice', _set_grip_from_client)
        add_callback(self.grip, 'value', _set_client_from_grip)
Beispiel #8
0
    def add_tool(self, tool):

        if isinstance(tool, DropdownTool) and len(tool.subtools) > 0:
            menu = QtWidgets.QMenu(self)
            for t in tool.subtools:
                action = self._make_action(t)
                menu.addAction(action)
        elif len(tool.menu_actions()) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in tool.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
        else:
            menu = None

        action = self._make_action(tool, menu=menu)

        self.addAction(action)

        self.actions[tool.tool_id] = action

        # Bind tool visibility to tool.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)

        add_callback(tool, 'enabled', toggle)

        self.tools[tool.tool_id] = tool

        return action
Beispiel #9
0
def connect_bool_button(client, prop, widget):
    """ Connect widget.setChecked and client.prop

    client.prop should be a callback property
    """
    add_callback(client, prop, widget.setChecked)
    widget.toggled.connect(partial(setattr, client, prop))
Beispiel #10
0
 def __init__(self, viewer, **kwargs):
     super(SpectrumExtractorMode, self).__init__(viewer, **kwargs)
     self._roi_tool = qt_roi.QtRectangularROI(self._axes)  # default
     self._tool = SpectrumTool(self.viewer, self)
     self._release_callback = self._tool._update_profile
     self._move_callback = self._tool._move_profile
     self._roi_callback = None
     add_callback(viewer.client, 'display_data', self._display_data_hook)
Beispiel #11
0
 def __init__(self, viewer, **kwargs):
     super(SpectrumExtractorMode, self).__init__(viewer, **kwargs)
     self._roi_tool = qt_roi.QtRectangularROI(self._axes)  # default
     self._tool = SpectrumTool(self.viewer, self)
     self._release_callback = self._tool._update_profile
     self._move_callback = self._tool._move_profile
     self._roi_callback = None
     add_callback(viewer.client, 'display_data', self._display_data_hook)
Beispiel #12
0
def connect_int_spin(client, prop, widget):
    """
    Connect client.prop to widget.valueChanged

    client.prop should be a callback property
    """
    add_callback(client, prop, widget.setValue)
    widget.valueChanged.connect(partial(setattr, client, prop))
Beispiel #13
0
    def __init__(self, grip, **kwargs):
        self.grip = grip
        add_callback(grip, 'range', self._update)
        ax = grip.viewer.axes
        trans = blended_transform_factory(ax.transData, ax.transAxes)

        kwargs.setdefault('lw', 2)
        kwargs.setdefault('alpha', 0.5)
        kwargs.setdefault('c', '#ffb304')
        self._line, = ax.plot(self.x, self.y, transform=trans, **kwargs)
Beispiel #14
0
    def __init__(self, grip, **kwargs):
        self.grip = grip
        add_callback(grip, 'range', self._update)
        ax = grip.viewer.axes
        trans = blended_transform_factory(ax.transData, ax.transAxes)

        kwargs.setdefault('lw', 2)
        kwargs.setdefault('alpha', 0.5)
        kwargs.setdefault('c', '#ffb304')
        self._line, = ax.plot(self.x, self.y, transform=trans, **kwargs)
Beispiel #15
0
    def _mouse_modes(self):
        modes = []
        modes.append(("Rectangle", get_icon("glue_square"), lambda tf: self._set_roi_mode("rectangle", tf)))
        modes.append(("Circle", get_icon("glue_circle"), lambda tf: self._set_roi_mode("circle", tf)))
        modes.append(("Polygon", get_icon("glue_lasso"), lambda tf: self._set_roi_mode("polygon", tf)))

        for tool in self._tools:
            modes += tool._get_modes(self.canvas)
            add_callback(self.client, "display_data", tool._display_data_hook)

        return modes
Beispiel #16
0
    def _mouse_modes(self):
        modes = []
        modes.append(("Rectangle", get_icon('glue_square'),
                      lambda tf: self._set_roi_mode('rectangle', tf)))
        modes.append(("Circle", get_icon('glue_circle'),
                      lambda tf: self._set_roi_mode('circle', tf)))
        modes.append(("Polygon", get_icon('glue_lasso'),
                      lambda tf: self._set_roi_mode('polygon', tf)))

        for tool in self._tools:
            modes += tool._get_modes(self.viewer)
            add_callback(self.client, 'display_data', tool._display_data_hook)

        return modes
Beispiel #17
0
    def new_value_grip(self, callback=None):
        """
        Create and return new ValueGrip

        :param callback: A callback function to be invoked
        whenever the grip.value property changes
        """
        result = self.value_cls(self)
        result.value = self._center[0]

        if callback is not None:
            add_callback(result, 'value', callback)
        self.grips.append(result)
        self.active_grip = result
        return result
Beispiel #18
0
    def _connect(self):

        add_callback(self.viewer_state, 'x_att', self.reset)
        add_callback(self.viewer_state, 'y_att', self.reset)

        def _on_tab_change(index):
            for i, ctx in enumerate(self._contexts):
                ctx.set_enabled(i == index)
                if i == index:
                    self.profile.active_grip = ctx.grip

        self._tabs.currentChanged.connect(_on_tab_change)
        _on_tab_change(self._tabs.currentIndex())

        self.widget.subset_dropped.connect(self._extract_subset_profile)
Beispiel #19
0
    def new_value_grip(self, callback=None):
        """
        Create and return new ValueGrip

        :param callback: A callback function to be invoked
        whenever the grip.value property changes
        """
        result = self.value_cls(self)
        result.value = self._center[0]

        if callback is not None:
            add_callback(result, 'value', callback)
        self.grips.append(result)
        self.active_grip = result
        return result
Beispiel #20
0
    def _connect(self):
        add_callback(self.client, 'slice',
                     self._check_invalidate,
                     echo_old=True)

        def _on_tab_change(index):
            for i, ctx in enumerate(self._contexts):
                ctx.set_enabled(i == index)
                if i == index:
                    self.profile.active_grip = ctx.grip

        self._tabs.currentChanged.connect(_on_tab_change)
        _on_tab_change(self._tabs.currentIndex())

        self.widget.subset_dropped.connect(self._extract_subset_profile)
Beispiel #21
0
    def _connect(self):

        add_callback(self.viewer_state, 'x_att',
                     self.reset)
        add_callback(self.viewer_state, 'y_att',
                     self.reset)

        def _on_tab_change(index):
            for i, ctx in enumerate(self._contexts):
                ctx.set_enabled(i == index)
                if i == index:
                    self.profile.active_grip = ctx.grip

        self._tabs.currentChanged.connect(_on_tab_change)
        _on_tab_change(self._tabs.currentIndex())

        self.widget.subset_dropped.connect(self._extract_subset_profile)
Beispiel #22
0
    def add_mode(self, mode):
        parent = QtWidgets.QToolBar.parent(self)

        def toggle():
            self._custom_mode(mode)

        def enable():
            # turn on if not
            if self._active != mode.mode_id:
                self._custom_mode(mode)

        action = QtWidgets.QAction(mode.icon, mode.action_text, parent)
        action.triggered.connect(nonpartial(toggle))
        parent.addAction(action)

        self.__signals.extend([toggle, enable])

        if mode.shortcut is not None:
            action.setShortcut(mode.shortcut)
            action.setShortcutContext(Qt.WidgetShortcut)

        action.setToolTip(mode.tool_tip)
        action.setCheckable(True)
        self.buttons[mode.mode_id] = action

        menu_actions = mode.menu_actions()
        if len(menu_actions) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in mode.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
            action.setMenu(menu)
            menu.triggered.connect(nonpartial(enable))

        self.addAction(action)

        # bind action status to mode.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)

        add_callback(mode, 'enabled', toggle)

        return action
Beispiel #23
0
    def new_range_grip(self, callback=None):
        """
        Create and return new RangeGrip

        :param callback: A callback function to be invoked
        whenever the grip.range property changes
        """
        result = self.range_cls(self)
        center = self._center[0]
        width = self._width
        result.range = center - width / 4, center + width / 4

        if callback is not None:
            add_callback(result, 'range', callback)

        self.grips.append(result)
        self.active_grip = result

        return result
Beispiel #24
0
    def new_range_grip(self, callback=None):
        """
        Create and return new RangeGrip

        :param callback: A callback function to be invoked
        whenever the grip.range property changes
        """
        result = self.range_cls(self)
        center = self._center[0]
        width = self._width
        result.range = center - width / 4, center + width / 4

        if callback is not None:
            add_callback(result, 'range', callback)

        self.grips.append(result)
        self.active_grip = result

        return result
Beispiel #25
0
    def add_mode(self, mode):
        parent = QtGui.QToolBar.parent(self)

        def toggle():
            self._custom_mode(mode)

        def enable():
            # turn on if not
            if self._active != mode.mode_id:
                self._custom_mode(mode)

        action = QtGui.QAction(mode.icon, mode.action_text, parent)
        action.triggered.connect(nonpartial(toggle))
        parent.addAction(action)

        self.__signals.extend([toggle, enable])

        if mode.shortcut is not None:
            action.setShortcut(mode.shortcut)
            action.setShortcutContext(Qt.WidgetShortcut)

        action.setToolTip(mode.tool_tip)
        action.setCheckable(True)
        self.buttons[mode.mode_id] = action

        menu_actions = mode.menu_actions()
        if len(menu_actions) > 0:
            menu = QtGui.QMenu(self)
            for ma in mode.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
            action.setMenu(menu)
            menu.triggered.connect(nonpartial(enable))

        self.addAction(action)

        # bind action status to mode.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)
        add_callback(mode, 'enabled', toggle)

        return action
Beispiel #26
0
    def _connect(self):
        ui = self.ui

        ui.monochrome.toggled.connect(self._update_rgb_console)
        ui.rgb_options.colors_changed.connect(self.update_window_title)

        # sync client and widget slices
        ui.slice.slice_changed.connect(lambda: setattr(self, 'slice', self.ui.slice.slice))
        update_ui_slice = lambda val: setattr(ui.slice, 'slice', val)
        add_callback(self.client, 'slice', update_ui_slice)
        add_callback(self.client, 'display_data', self.ui.slice.set_data)

        # sync window title to data/attribute
        add_callback(self.client, 'display_data', nonpartial(self._display_data_changed))
        add_callback(self.client, 'display_attribute', nonpartial(self._display_attribute_changed))
        add_callback(self.client, 'display_aspect', nonpartial(self.client._update_aspect))

        # sync data/attribute combos with client properties
        connect_current_combo(self.client, 'display_data', self.ui.displayDataCombo)
        connect_current_combo(self.client, 'display_attribute', self.ui.attributeComboBox)
        connect_current_combo(self.client, 'display_aspect', self.ui.aspectCombo)
Beispiel #27
0
    def _setup_grip(self):
        def _set_state_from_grip(value):
            """Update state.slices given grip value"""
            if not self.main.enabled:
                return

            slc = list(self.viewer_state.slices)
            # state.slices stored in pixel coords
            value = Extractor.world2pixel(
                self.data,
                self.profile_axis, value)
            slc[self.profile_axis] = value

            # prevent callback bouncing. Fixes #298
            self.viewer_state.slices = tuple(slc)

        def _set_grip_from_state(slc):
            """Update grip.value given state.slices"""
            if not self.main.enabled:
                return

            # grip.value is stored in world coordinates
            val = slc[self.profile_axis]

            if isinstance(val, AggregateSlice):
                val = val.center

            val = Extractor.pixel2world(self.data, self.profile_axis, val)

            # If pix2world not monotonic, this can trigger infinite recursion.
            # Avoid by disabling callback loop
            # XXX better to specifically ignore _set_state_from_grip
            with ignore_callback(self.grip, 'value'):
                self.grip.value = val

        self.grip = self.main.profile.new_value_grip()

        add_callback(self.viewer_state, 'slices', _set_grip_from_state)
        add_callback(self.grip, 'value', _set_state_from_grip)
Beispiel #28
0
    def _setup_grip(self):
        def _set_state_from_grip(value):
            """Update state.slices given grip value"""
            if not self.main.enabled:
                return

            slc = list(self.viewer_state.slices)
            # state.slices stored in pixel coords
            value = Extractor.world2pixel(
                self.data,
                self.profile_axis, value)
            slc[self.profile_axis] = value

            # prevent callback bouncing. Fixes #298
            self.viewer_state.slices = tuple(slc)

        def _set_grip_from_state(slc):
            """Update grip.value given state.slices"""
            if not self.main.enabled:
                return

            # grip.value is stored in world coordinates
            val = slc[self.profile_axis]

            if isinstance(val, AggregateSlice):
                val = val.center

            val = Extractor.pixel2world(self.data, self.profile_axis, val)

            # If pix2world not monotonic, this can trigger infinite recursion.
            # Avoid by disabling callback loop
            # XXX better to specifically ignore _set_state_from_grip
            with ignore_callback(self.grip, 'value'):
                self.grip.value = val

        self.grip = self.main.profile.new_value_grip()

        add_callback(self.viewer_state, 'slices', _set_grip_from_state)
        add_callback(self.grip, 'value', _set_state_from_grip)
Beispiel #29
0
    def _setup_grip(self):
        def _set_client_from_grip(value):
            """Update client.slice given grip value"""
            if not self.main.enabled:
                return

            slc = list(self.client.slice)
            # client.slice stored in pixel coords
            value = Extractor.world2pixel(
                self.data,
                self.profile_axis, value)
            slc[self.profile_axis] = value

            # prevent callback bouncing. Fixes #298
            with ignore_callback(self.grip, 'value'):
                self.client.slice = tuple(slc)

        def _set_grip_from_client(slc):
            """Update grip.value given client.slice"""
            if not self.main.enabled:
                return

            # grip.value is stored in world coordinates
            val = slc[self.profile_axis]
            val = Extractor.pixel2world(self.data, self.profile_axis, val)

            # If pix2world not monotonic, this can trigger infinite recursion.
            # Avoid by disabling callback loop
            # XXX better to specifically ignore _set_client_from_grip
            with ignore_callback(self.client, 'slice'):
                self.grip.value = val

        self.grip = self.main.profile.new_value_grip()

        add_callback(self.client, 'slice', _set_grip_from_client)
        add_callback(self.grip, 'value', _set_client_from_grip)
Beispiel #30
0
 def _connect(self):
     add_callback(self, 'ylog', self._set_ylog)
     add_callback(self, 'height_attr', nonpartial(self._relayout))
     add_callback(self, 'order_attr', nonpartial(self._relayout))
     add_callback(self, 'parent_attr', nonpartial(self._relayout))
Beispiel #31
0
    def _connect(self):
        add_callback(self, 'xlog', self._set_xlog)
        add_callback(self, 'ylog', self._set_ylog)

        add_callback(self, 'xflip', self._set_limits)
        add_callback(self, 'yflip', self._set_limits)
        add_callback(self, 'xmin', self._set_limits)
        add_callback(self, 'xmax', self._set_limits)
        add_callback(self, 'ymin', self._set_limits)
        add_callback(self, 'ymax', self._set_limits)
        add_callback(self, 'xatt', partial(self._set_xydata, 'x'))
        add_callback(self, 'yatt', partial(self._set_xydata, 'y'))
        add_callback(self, 'jitter', self._jitter)
        self.axes.figure.canvas.mpl_connect('draw_event',
                                            lambda x: self._pull_properties())
Beispiel #32
0
    def add_tool(self, tool):

        parent = QtWidgets.QToolBar.parent(self)

        if isinstance(tool.icon, six.string_types):
            if os.path.exists(tool.icon):
                icon = QtGui.QIcon(tool.icon)
            else:
                icon = get_icon(tool.icon)
        else:
            icon = tool.icon

        action = QtWidgets.QAction(icon, tool.action_text, parent)

        def toggle(checked):
            if checked:
                self.active_tool = tool
            else:
                self.active_tool = None

        def trigger(checked):
            self.active_tool = tool

        parent.addAction(action)

        if isinstance(tool, CheckableTool):
            action.toggled.connect(toggle)
        else:
            action.triggered.connect(trigger)

        shortcut = None

        if tool.shortcut is not None:

            # Make sure that the keyboard shortcut is unique
            for m in self.tools.values():
                if tool.shortcut == m.shortcut:
                    warnings.warn("Tools '{0}' and '{1}' have the same shortcut "
                                  "('{2}'). Ignoring shortcut for "
                                  "'{1}'".format(m.tool_id, tool.tool_id, tool.shortcut))
                    break
            else:
                shortcut = tool.shortcut
                action.setShortcut(tool.shortcut)
                action.setShortcutContext(Qt.WidgetShortcut)

        if shortcut is None:
            action.setToolTip(tool.tool_tip)
        else:
            action.setToolTip(tool.tool_tip + " [shortcut: {0}]".format(shortcut))

        action.setCheckable(isinstance(tool, CheckableTool))
        self.actions[tool.tool_id] = action

        menu_actions = tool.menu_actions()
        if len(menu_actions) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in tool.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
            action.setMenu(menu)
            menu.triggered.connect(trigger)

        self.addAction(action)

        # Bind tool visibility to tool.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)
        add_callback(tool, 'enabled', toggle)

        self.tools[tool.tool_id] = tool

        return action
Beispiel #33
0
    def _connect(self):
        add_callback(self, 'xlog', self._set_xlog)
        add_callback(self, 'ylog', self._set_ylog)

        add_callback(self, 'xflip', self._set_limits)
        add_callback(self, 'yflip', self._set_limits)
        add_callback(self, 'xmin', self._set_limits)
        add_callback(self, 'xmax', self._set_limits)
        add_callback(self, 'ymin', self._set_limits)
        add_callback(self, 'ymax', self._set_limits)
        add_callback(self, 'xatt', partial(self._set_xydata, 'x'))
        add_callback(self, 'yatt', partial(self._set_xydata, 'y'))
        add_callback(self, 'jitter', self._jitter)
        self.axes.figure.canvas.mpl_connect('draw_event',
                                            lambda x: self._pull_properties())
Beispiel #34
0
    def add_tool(self, tool):

        parent = QtWidgets.QToolBar.parent(self)

        if isinstance(tool.icon, six.string_types):
            if os.path.exists(tool.icon):
                icon = QtGui.QIcon(tool.icon)
            else:
                icon = get_icon(tool.icon)
        else:
            icon = tool.icon

        action = QtWidgets.QAction(icon, tool.action_text, parent)

        def toggle(checked):
            if checked:
                self.active_tool = tool
            else:
                self.active_tool = None

        def trigger(checked):
            self.active_tool = tool

        parent.addAction(action)

        if isinstance(tool, CheckableTool):
            action.toggled.connect(toggle)
        else:
            action.triggered.connect(trigger)

        shortcut = None

        if tool.shortcut is not None:

            # Make sure that the keyboard shortcut is unique
            for m in self.tools.values():
                if tool.shortcut == m.shortcut:
                    warnings.warn(
                        "Tools '{0}' and '{1}' have the same shortcut "
                        "('{2}'). Ignoring shortcut for "
                        "'{1}'".format(m.tool_id, tool.tool_id, tool.shortcut))
                    break
            else:
                shortcut = tool.shortcut
                action.setShortcut(tool.shortcut)
                action.setShortcutContext(Qt.WidgetShortcut)

        if shortcut is None:
            action.setToolTip(tool.tool_tip)
        else:
            action.setToolTip(tool.tool_tip +
                              " [shortcut: {0}]".format(shortcut))

        action.setCheckable(isinstance(tool, CheckableTool))
        self.actions[tool.tool_id] = action

        menu_actions = tool.menu_actions()
        if len(menu_actions) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in tool.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
            action.setMenu(menu)
            menu.triggered.connect(trigger)

        self.addAction(action)

        # Bind tool visibility to tool.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)

        add_callback(tool, 'enabled', toggle)

        self.tools[tool.tool_id] = tool

        return action
Beispiel #35
0
 def _connect(self):
     add_callback(self, 'ylog', self._set_ylog)
     add_callback(self, 'height_attr', nonpartial(self._relayout))
     add_callback(self, 'order_attr', nonpartial(self._relayout))
     add_callback(self, 'parent_attr', nonpartial(self._relayout))