Source code for uwsift.view.algebraic_config

import logging
from functools import partial
from typing import Optional, Tuple

from PyQt5.QtCore import QObject, pyqtSignal
from PyQt5.QtWidgets import QComboBox

from uwsift.common import Kind
from uwsift.model.composite_recipes import (
    CUSTOM_OP_NAME,
    DIFF_OP_NAME,
    PRESET_OPERATIONS,
    AlgebraicRecipe,
)
from uwsift.model.layer_item import LayerItem
from uwsift.model.layer_model import LayerModel

LOG = logging.getLogger(__name__)


[docs] class AlgebraicLayerConfigPane(QObject): # Recipe, Channel, layer uuid didChangeAlgebraicInputLayers = pyqtSignal(AlgebraicRecipe, str, object) # Recipe, operation kind didChangeAlgebraicOperationKind = pyqtSignal(AlgebraicRecipe, str) # Recipe, operation kind didChangeAlgebraicOperationFormula = pyqtSignal(AlgebraicRecipe, str) didChangeRecipeName = pyqtSignal(AlgebraicRecipe, str) didTriggeredUpdate = pyqtSignal(AlgebraicRecipe) _operation_combo = None _operations_text = None _algebraic_name_edit = None _algebraic_channels = None _custom_formula = None def __init__(self, ui, parent, model: LayerModel): super(AlgebraicLayerConfigPane, self).__init__(parent) self.ui = ui self._layer_uuids: list = [] self.recipe: Optional[AlgebraicRecipe] = None self.model = model [ x.currentIndexChanged.connect(partial(self._combo_changed, combo=x, channel=xyz)) for xyz, x in zip(("z", "y", "x"), (self.ui.z_combo, self.ui.y_combo, self.ui.x_combo)) ] self.ui.layer_name_edit.textEdited.connect(self._algebraic_name_edit_changed) self.ui.operations_text.textChanged.connect(self._operation_formular_changed) self.ui.algebraicUpdateButton.clicked.connect(self._on_algebraic_update_button_clicked) self._algebraic_name_edit = self.ui.layer_name_edit self._operation_combo = self.ui.operation_combo self._operations_text = self.ui.operations_text self._init_operation_selection() self._set_combos_to_layer_names() self._show_settings_for_layer() @property def algebraic_channels(self): if self._algebraic_channels is None: self._algebraic_channels = [self.ui.x_combo, self.ui.y_combo, self.ui.z_combo] return self._algebraic_channels @property def algebraic_name_edit(self): return self._algebraic_name_edit @property def operation_combo(self): return self._operation_combo @property def operations_text(self): return self._operations_text
[docs] def layer_added(self, layer: LayerItem): if layer.kind in [Kind.IMAGE] and layer.recipe is None: self._layer_uuids.append(layer.uuid) self._set_combos_to_layer_names()
[docs] def layer_removed(self, layer_uuid): if layer_uuid in self._layer_uuids: idx = self._layer_uuids.index(layer_uuid) del self._layer_uuids[idx] self._set_combos_to_layer_names() self._show_settings_for_layer(self.recipe)
def _combo_changed(self, index, combo: QComboBox = None, channel=None): layer_uuid = combo.itemData(index) if not layer_uuid: layer_uuid = None LOG.debug(f"Algebraic: user selected {repr(layer_uuid)} for {channel}") self.didChangeAlgebraicInputLayers.emit(self.recipe, channel, layer_uuid) self._show_settings_for_layer(self.recipe) def _algebraic_name_edit_changed(self, text): self.didChangeRecipeName.emit(self.recipe, text)
[docs] def selection_did_change(self, layers: Tuple[LayerItem]): """Change UI elements to reflect the provided recipe""" if layers is not None and len(layers) == 1: layer = layers[0] self.recipe = layer.recipe if isinstance(layer.recipe, AlgebraicRecipe) else None self._show_settings_for_layer(self.recipe)
def _show_settings_for_layer(self, recipe=None): if not isinstance(recipe, AlgebraicRecipe): self.ui.algebraicScrollAreaWidgetContents.setDisabled(True) return else: self.ui.algebraicScrollAreaWidgetContents.setDisabled(False) for widget in self.algebraic_channels: widget.blockSignals(True) # Update widgets self._select_components_for_recipe(recipe) self._set_algebraic_name_edit(recipe) self._select_operation_of_recipe(recipe) for widget in self.algebraic_channels: widget.blockSignals(False) def _select_components_for_recipe(self, recipe=None): if recipe is not None: for layer_uuid, widget in zip(recipe.input_layer_ids, self.algebraic_channels): if not layer_uuid: widget.setCurrentIndex(0) else: dex = widget.findData(layer_uuid) if dex <= 0: widget.setCurrentIndex(0) LOG.error(f"Layer with uuid '{layer_uuid}' not" f" available to be selected") else: widget.setCurrentIndex(dex) else: for widget in self.algebraic_channels: widget.setCurrentIndex(0) def _set_algebraic_name_edit(self, recipe): if recipe is not None: self.algebraic_name_edit.setText(recipe.name) else: self.algebraic_name_edit.setText("") def _set_combos_to_layer_names(self): """ update combo boxes with the list of layer names and then select the right x, y, z layers if they're not None """ current_layers = [x.itemData(x.currentIndex()) for x in self.algebraic_channels] for widget in self.algebraic_channels: widget.blockSignals(True) for widget in self.algebraic_channels: widget.clear() widget.addItem("None", None) for widget, selected_layer_uuid in zip(self.algebraic_channels, current_layers): if not selected_layer_uuid or selected_layer_uuid not in self._layer_uuids: widget.setCurrentIndex(0) for idx, layer_uuid in enumerate(self._layer_uuids): layer: LayerItem = self.model.get_layer_by_uuid(layer_uuid) display_name = layer.descriptor widget.addItem(display_name, layer_uuid) widget.findData(layer_uuid) if layer_uuid == selected_layer_uuid: widget.setCurrentIndex(idx + 1) for widget in self.algebraic_channels: widget.blockSignals(False) def _init_operation_selection(self): for op_name in PRESET_OPERATIONS.keys(): self.operation_combo.addItem(op_name) self.operation_combo.addItem(CUSTOM_OP_NAME) self.operation_combo.setCurrentIndex(0) self.operation_combo.currentIndexChanged.connect(self._set_operation) self.ui.operation_combo.currentIndexChanged.connect(self._operation_kind_changed) self._custom_formula = PRESET_OPERATIONS[DIFF_OP_NAME][0] def _set_operation(self, *args, **kwargs): was_custom = self.operations_text.isEnabled() if was_custom: self._custom_formula = self.operations_text.toPlainText() operation = self.operation_combo.currentText() op_formular, num_layers = PRESET_OPERATIONS.get(operation, (None, 3)) if op_formular is None: op_formular = self._custom_formula self.operations_text.setDisabled(False) else: self.operations_text.setDisabled(True) self.operations_text.setPlainText(op_formular) for idx, combo in enumerate(self.algebraic_channels): combo.setDisabled(idx >= num_layers) def _select_operation_of_recipe(self, recipe): if recipe and isinstance(recipe, AlgebraicRecipe): dex = self.operation_combo.findText(recipe.operation_kind) self.operation_combo.setCurrentIndex(dex) self._set_operation() def _operation_kind_changed(self, index: QComboBox): operation_kind = self.operation_combo.itemText(index) self.didChangeAlgebraicOperationKind.emit(self.recipe, operation_kind) def _operation_formular_changed(self): self.didChangeAlgebraicOperationFormula.emit(self.recipe, self.operations_text.toPlainText()) def _on_algebraic_update_button_clicked(self): self.didTriggeredUpdate.emit(self.recipe)