diff --git a/orangecontrib/spectroscopy/widgets/owhyper.py b/orangecontrib/spectroscopy/widgets/owhyper.py index e695ac1b7..5a8b8fe1a 100644 --- a/orangecontrib/spectroscopy/widgets/owhyper.py +++ b/orangecontrib/spectroscopy/widgets/owhyper.py @@ -284,6 +284,31 @@ def color_palette_model(palettes, iconsize=QSize(64, 16)): return model +class AxesSettingsMixin: + + def __init__(self): + self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, + valid_types=DomainModel.PRIMITIVE) + + def setup_axes_settings_box(self): + box = gui.vBox(self) + + common_options = { + "labelWidth": 50, + "orientation": Qt.Horizontal, + "sendSelectedValue": True + } + + cb_attr_x = gui.comboBox( + box, self, "attr_x", label="Axis x:", callback=self.update_attr, + model=self.xy_model, **common_options) + gui.comboBox( + box, self, "attr_y", label="Axis y:", callback=self.update_attr, + model=self.xy_model, **common_options) + box.setFocusProxy(cb_attr_x) + return box + + class ImageColorSettingMixin: threshold_low = Setting(0.0, schema_only=True) threshold_high = Setting(1.0, schema_only=True) @@ -529,6 +554,53 @@ def add_zoom_actions(self, menu): menu.addAction(zoom_fit) +class ImageSelectionMixin: + + def add_selection_actions(self, menu): + + select_square = QAction( + "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, + ) + select_square.setShortcuts([Qt.Key_S]) + select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) + self.addAction(select_square) + if menu: + menu.addAction(select_square) + + select_polygon = QAction( + "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, + ) + select_polygon.setShortcuts([Qt.Key_P]) + select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) + self.addAction(select_polygon) + if menu: + menu.addAction(select_polygon) + + def select_square(self, p1, p2): + """ Select elements within a square drawn by the user. + A selection needs to contain whole pixels """ + x1, y1 = p1.x(), p1.y() + x2, y2 = p2.x(), p2.y() + polygon = [QPointF(x1, y1), QPointF(x2, y1), QPointF(x2, y2), QPointF(x1, y2), QPointF(x1, y1)] + self.select_polygon(polygon) + + def select_polygon(self, polygon): + """ Select by a polygon which has to contain whole pixels. """ + if self.data and self.lsx and self.lsy: + polygon = [(p.x(), p.y()) for p in polygon] + # a polygon should contain all pixel + shiftx = _shift(self.lsx) + shifty = _shift(self.lsy) + points_edges = [self.data_points + [[shiftx, shifty]], + self.data_points + [[-shiftx, shifty]], + self.data_points + [[shiftx, -shifty]], + self.data_points + [[-shiftx, -shifty]]] + inp = in_polygon(points_edges[0], polygon) + for p in points_edges[1:]: + inp *= in_polygon(p, polygon) + self.make_selection(inp) + + class ImageColorLegend(GraphicsWidget): def __init__(self): @@ -622,12 +694,11 @@ def legend_items(self): return [] -class ImagePlot(QWidget, OWComponent, SelectionGroupMixin, - ImageColorSettingMixin, ImageRGBSettingMixin, - ImageZoomMixin, ConcurrentMixin): +class BasicImagePlot(QWidget, OWComponent, SelectionGroupMixin, + AxesSettingsMixin, ImageSelectionMixin, + ImageColorSettingMixin, ImageRGBSettingMixin, + ImageZoomMixin, ConcurrentMixin): - attr_x = ContextSetting(None, exclude_attributes=True) - attr_y = ContextSetting(None, exclude_attributes=True) gamma = Setting(0) selection_changed = Signal() @@ -637,6 +708,8 @@ def __init__(self, parent): QWidget.__init__(self) OWComponent.__init__(self, parent) SelectionGroupMixin.__init__(self) + AxesSettingsMixin.__init__(self) + ImageSelectionMixin.__init__(self) ImageColorSettingMixin.__init__(self) ImageZoomMixin.__init__(self) ConcurrentMixin.__init__(self) @@ -694,56 +767,28 @@ def __init__(self, parent): # prepare interface according to the new context self.parent.contextAboutToBeOpened.connect(lambda x: self.init_interface_data(x[0])) - actions = [] - self.add_zoom_actions(view_menu) - - select_square = QAction( - "Select (square)", self, triggered=self.plot.vb.set_mode_select_square, - ) - select_square.setShortcuts([Qt.Key_S]) - select_square.setShortcutContext(Qt.WidgetWithChildrenShortcut) - actions.append(select_square) - - select_polygon = QAction( - "Select (polygon)", self, triggered=self.plot.vb.set_mode_select_polygon, - ) - select_polygon.setShortcuts([Qt.Key_P]) - select_polygon.setShortcutContext(Qt.WidgetWithChildrenShortcut) - actions.append(select_polygon) + self.add_selection_actions(view_menu) if self.saving_enabled: save_graph = QAction( "Save graph", self, triggered=self.save_graph, ) save_graph.setShortcuts([QKeySequence(Qt.ControlModifier | Qt.Key_I)]) - actions.append(save_graph) - - view_menu.addActions(actions) - self.addActions(actions) - for a in actions: - a.setShortcutVisibleInContextMenu(True) - - common_options = dict( - labelWidth=50, orientation=Qt.Horizontal, sendSelectedValue=True) + self.addAction(save_graph) + view_menu.addAction(save_graph) + save_graph.setShortcutVisibleInContextMenu(True) choose_xy = QWidgetAction(self) box = gui.vBox(self) box.setContentsMargins(10, 0, 10, 0) box.setFocusPolicy(Qt.TabFocus) - self.xy_model = DomainModel(DomainModel.METAS | DomainModel.CLASSES, - valid_types=DomainModel.PRIMITIVE) - self.cb_attr_x = gui.comboBox( - box, self, "attr_x", label="Axis x:", callback=self.update_attr, - model=self.xy_model, **common_options) - self.cb_attr_y = gui.comboBox( - box, self, "attr_y", label="Axis y:", callback=self.update_attr, - model=self.xy_model, **common_options) - box.setFocusProxy(self.cb_attr_x) + self.axes_settings_box = self.setup_axes_settings_box() self.color_settings_box = self.setup_color_settings_box() self.rgb_settings_box = self.setup_rgb_settings_box() + box.layout().addWidget(self.axes_settings_box) box.layout().addWidget(self.color_settings_box) box.layout().addWidget(self.rgb_settings_box) @@ -830,30 +875,6 @@ def make_selection(self, selected): self.prepare_settings_for_saving() self.selection_changed.emit() - def select_square(self, p1, p2): - """ Select elements within a square drawn by the user. - A selection needs to contain whole pixels """ - x1, y1 = p1.x(), p1.y() - x2, y2 = p2.x(), p2.y() - polygon = [QPointF(x1, y1), QPointF(x2, y1), QPointF(x2, y2), QPointF(x1, y2), QPointF(x1, y1)] - self.select_polygon(polygon) - - def select_polygon(self, polygon): - """ Select by a polygon which has to contain whole pixels. """ - if self.data and self.lsx and self.lsy: - polygon = [(p.x(), p.y()) for p in polygon] - # a polygon should contain all pixel - shiftx = _shift(self.lsx) - shifty = _shift(self.lsy) - points_edges = [self.data_points + [[shiftx, shifty]], - self.data_points + [[-shiftx, shifty]], - self.data_points + [[shiftx, -shifty]], - self.data_points + [[-shiftx, -shifty]]] - inp = in_polygon(points_edges[0], polygon) - for p in points_edges[1:]: - inp *= in_polygon(p, polygon) - self.make_selection(inp) - def _points_at_pos(self, pos): if self.data and self.lsx and self.lsy: x, y = pos.x(), pos.y() @@ -1020,6 +1041,11 @@ def on_exception(self, ex: Exception): raise ex +class ImagePlot(BasicImagePlot): + attr_x = ContextSetting(None, exclude_attributes=True) + attr_y = ContextSetting(None, exclude_attributes=True) + + class CurvePlotHyper(CurvePlot): viewtype = Setting(AVERAGE) # average view by default