class FlipRotateMixin(base.BaseTransformMixin): """Rotate & Crop mixin class, to be mixed with a class providing the get_plot method, like ImageDialog or FlipRotateWidget (see below)""" ROTATION_ANGLES = [str((i - 1) * 90) for i in range(4)] #------BaseTransformMixin API---------------------------------------------- def add_buttons_to_layout(self, layout): """Add tool buttons to layout""" # Image orientation angle_label = QLabel(_("Angle (°):")) layout.addWidget(angle_label) self.angle_combo = QComboBox(self) self.angle_combo.addItems(self.ROTATION_ANGLES) self.angle_combo.setCurrentIndex(1) self.angle_combo.currentIndexChanged.connect( lambda index: self.apply_transformation()) layout.addWidget(self.angle_combo) layout.addSpacing(10) # Image flipping flip_label = QLabel(_("Flip:")) layout.addWidget(flip_label) hflip = create_toolbutton( self, text="", icon=get_icon("hflip.png"), toggled=lambda state: self.apply_transformation(), autoraise=False) self.hflip_btn = hflip layout.addWidget(hflip) vflip = create_toolbutton( self, text="", icon=get_icon("vflip.png"), toggled=lambda state: self.apply_transformation(), autoraise=False) self.vflip_btn = vflip layout.addWidget(vflip) layout.addSpacing(15) self.add_reset_button(layout) def reset_transformation(self): """Reset transformation""" self.angle_combo.setCurrentIndex(1) self.hflip_btn.setChecked(False) self.vflip_btn.setChecked(False) def apply_transformation(self): """Apply transformation, e.g. crop or rotate""" angle, hflip, vflip = self.get_parameters() x, y, _a, px, py, _hf, _vf = self.item.get_transform() self.item.set_transform(x, y, angle * np.pi / 180, px, py, hflip, vflip) self.get_plot().replot() def compute_transformation(self): """Compute transformation, return compute output array""" angle, hflip, vflip = self.get_parameters() data = self.item.data.copy() if hflip: data = np.fliplr(data) if vflip: data = np.flipud(data) if angle: k = int((-angle % 360) / 90) data = np.rot90(data, k) return data #------Public API---------------------------------------------------------- def get_parameters(self): """Return transform parameters""" angle = int(str(self.angle_combo.currentText())) hflip = self.hflip_btn.isChecked() vflip = self.vflip_btn.isChecked() return angle, hflip, vflip def set_parameters(self, angle, hflip, vflip): """Set transform parameters""" angle_index = self.ROTATION_ANGLES.index(str(angle)) self.angle_combo.setCurrentIndex(angle_index) self.hflip_btn.setChecked(hflip) self.vflip_btn.setChecked(vflip)
class FlipRotateMixin(base.BaseTransformMixin): """Rotate & Crop mixin class, to be mixed with a class providing the get_plot method, like ImageDialog or FlipRotateWidget (see below)""" ROTATION_ANGLES = [str((i-1)*90) for i in range(4)] #------BaseTransformMixin API---------------------------------------------- def add_buttons_to_layout(self, layout): """Add tool buttons to layout""" # Image orientation angle_label = QLabel(_("Angle (°):")) layout.addWidget(angle_label) self.angle_combo = QComboBox(self) self.angle_combo.addItems(self.ROTATION_ANGLES) self.angle_combo.setCurrentIndex(1) self.angle_combo.currentIndexChanged.connect( lambda index: self.apply_transformation()) layout.addWidget(self.angle_combo) layout.addSpacing(10) # Image flipping flip_label = QLabel(_("Flip:")) layout.addWidget(flip_label) hflip = create_toolbutton(self, text="", icon=get_icon("hflip.png"), toggled=lambda state: self.apply_transformation(), autoraise=False) self.hflip_btn = hflip layout.addWidget(hflip) vflip = create_toolbutton(self, text="", icon=get_icon("vflip.png"), toggled=lambda state: self.apply_transformation(), autoraise=False) self.vflip_btn = vflip layout.addWidget(vflip) layout.addSpacing(15) self.add_reset_button(layout) def reset_transformation(self): """Reset transformation""" self.angle_combo.setCurrentIndex(1) self.hflip_btn.setChecked(False) self.vflip_btn.setChecked(False) def apply_transformation(self): """Apply transformation, e.g. crop or rotate""" angle, hflip, vflip = self.get_parameters() x, y, _a, px, py, _hf, _vf = self.item.get_transform() self.item.set_transform(x, y, angle*np.pi/180, px, py, hflip, vflip) self.get_plot().replot() def compute_transformation(self): """Compute transformation, return compute output array""" angle, hflip, vflip = self.get_parameters() data = self.item.data.copy() if hflip: data = np.fliplr(data) if vflip: data = np.flipud(data) if angle: k = int( (-angle % 360)/90 ) data = np.rot90(data, k) return data #------Public API---------------------------------------------------------- def get_parameters(self): """Return transform parameters""" angle = int(str(self.angle_combo.currentText())) hflip = self.hflip_btn.isChecked() vflip = self.vflip_btn.isChecked() return angle, hflip, vflip def set_parameters(self, angle, hflip, vflip): """Set transform parameters""" angle_index = self.ROTATION_ANGLES.index(str(angle)) self.angle_combo.setCurrentIndex(angle_index) self.hflip_btn.setChecked(hflip) self.vflip_btn.setChecked(vflip)
class OperationsWidget(QWidget): operations_changed = QtCore.pyqtSignal() operation_changed = QtCore.pyqtSignal(dict, int) operation_added = QtCore.pyqtSignal(dict, int) def __init__(self, parent=None): QWidget.__init__(self, parent) self.widget_layout = QVBoxLayout() title_layout = QHBoxLayout() title_layout.addStretch() style = "<span style=\'color: #444444\'><b>%s</b></span>" title = QLabel(style % "Operations") title_layout.addWidget(title) title_layout.addStretch() self.widget_layout.addLayout(title_layout) # Create ListWidget and add 10 items to move around. self.list_widget = QListWidget() # self.list_widget.setDragDropMode(QAbstractItemView.InternalMove) self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setSortingEnabled(False) self.list_widget.currentItemChanged.connect(self._populate_settings_update) self.widget_layout.addWidget(self.list_widget) otitle_layout = QHBoxLayout() otitle_layout.addStretch() otitle = QLabel(style % "Operation settings") otitle_layout.addWidget(otitle) otitle_layout.addStretch() self.widget_layout.addLayout(otitle_layout) self.operations_combo = QComboBox() self.operations_combo.currentIndexChanged.connect(self._populate_settings_add) self.widget_layout.addWidget(self.operations_combo) self.operation_settings = GenericOperationWidget() self.widget_layout.addWidget(self.operation_settings) self.toolbar = QToolBar() self.toolbar.addAction(get_icon('apply.png'), "Apply/Replace", self._change_operation) self.toolbar.addAction(get_icon('editors/edit_add.png'), "Add after", self._add_operation) self.toolbar.addAction(get_icon('trash.png'), "Remove", self._remove_operation) self.widget_layout.addWidget(self.toolbar) self.setLayout(self.widget_layout) def populate_available_operations(self, dict): """ Populate combobox with available operation names """ self.operations_combo.addItems(dict) def set_operations(self, operations_dict): """ Populate operations list with given dict of operations """ self.list_widget.clear() for op in operations_dict: self.list_widget.addItem(Operation(op)) def get_operations(self): """ Return list of operations. """ operations = [] for i in range(self.list_widget.count()): op = self.list_widget.item(i) operations.append(op._op) return operations def _remove_operation(self): self.list_widget.takeItem(self.list_widget.currentRow()) self.operations_changed.emit() def _add_operation(self): """ Add operation currently in self.operation_settings to the operation list. Signals: ======== Emits self.opeartion_added and self.operations_changed on success """ op = self.operation_settings.get_operation() current_row = self.list_widget.currentRow() self.list_widget.insertItem(current_row + 1, Operation(op)) index = self.list_widget.model().index(current_row + 1, 0) self.list_widget.setCurrentIndex(index) self.operation_added.emit(op, current_row + 1) self.operations_changed.emit() def _change_operation(self): """ Replace currently selected operation with operation in self.operation_settings (apply changed settings or replace operation). Signals: ======== Emits self.operation_changed and self.operations_changed on success """ op = self.operation_settings.get_operation() current_row = self.list_widget.currentRow() self.list_widget.takeItem(self.list_widget.currentRow()) self.list_widget.insertItem(current_row, Operation(op)) index = self.list_widget.model().index(current_row, 0) self.list_widget.setCurrentIndex(index) self.operation_changed.emit(op, current_row) self.operations_changed.emit() def _populate_settings_update(self, item): """ Fill self.operation_settings with details of currently selected operation. """ try: idx = self.operations_combo.findText(item._op["module"]) if idx >= 0: self.operations_combo.setCurrentIndex(idx) self.operation_settings.set_operation(item._op) except AttributeError: pass def _populate_settings_add(self, index): self.operation_settings.set_operation({"module": self.operations_combo.currentText()})