feat(controller_params): implement class ScanSlicerParamsMixin
This commit is contained in:
parent
4130a7b606
commit
e746fa4df6
1 changed files with 225 additions and 0 deletions
|
|
@ -2,3 +2,228 @@ from PySide6.QtWidgets import QComboBox, QInputDialog, QMessageBox, QSlider
|
|||
|
||||
|
||||
# ScanSlicerParamsMixin: class definition for ScanSlicer behavior.
|
||||
class ScanSlicerParamsMixin:
|
||||
# set_autotune_profile: function definition for ScanSlicer behavior.
|
||||
def set_autotune_profile(self, profile_name):
|
||||
normalized = self.autoslicer.normalize_autotune_profile(profile_name)
|
||||
self.autotune_profile = normalized
|
||||
|
||||
dropdown = getattr(self, "autotune_profile_dropdown", None)
|
||||
if dropdown is not None and dropdown.currentText() != normalized:
|
||||
dropdown.blockSignals(True)
|
||||
dropdown.setCurrentText(normalized)
|
||||
dropdown.blockSignals(False)
|
||||
|
||||
# set_show_advanced_parameters: function definition for ScanSlicer behavior.
|
||||
def set_show_advanced_parameters(self, checked):
|
||||
self.show_advanced_params = bool(checked)
|
||||
self.update_parameter_visibility()
|
||||
|
||||
# sync_param_controls_from_model: function definition for ScanSlicer behavior.
|
||||
def sync_param_controls_from_model(self):
|
||||
self.updating_param_controls = True
|
||||
for name, p in self.params.items():
|
||||
control = self.param_controls[name]
|
||||
if isinstance(control, QSlider):
|
||||
control.setValue(p.get())
|
||||
elif isinstance(control, QComboBox):
|
||||
idx = control.findData(p.get())
|
||||
if idx >= 0:
|
||||
control.setCurrentIndex(idx)
|
||||
self.updating_param_controls = False
|
||||
self.update_parameter_visibility()
|
||||
|
||||
# update_parameter_visibility: function definition for ScanSlicer behavior.
|
||||
def update_parameter_visibility(self):
|
||||
pipeline = self.params.detect_pipeline.get()
|
||||
method = self.params.bw_method.get()
|
||||
morph_op = self.params.morph_op.get()
|
||||
show_advanced = bool(getattr(self, "show_advanced_params", False))
|
||||
advanced_params = set(getattr(self, "ADVANCED_PARAMS", set()))
|
||||
|
||||
visibility = {
|
||||
"bw_method": pipeline == 0,
|
||||
"bw_thresh": pipeline == 0 and method == 0,
|
||||
"bw_gauss": pipeline == 0 and method == 1,
|
||||
"bw_adaptive_c": pipeline == 0 and method == 1,
|
||||
"canny_low": pipeline == 1,
|
||||
"canny_high": pipeline == 1,
|
||||
"dilate_kernel": morph_op != 0,
|
||||
}
|
||||
|
||||
for param_name, block in self.param_blocks.items():
|
||||
if block is None:
|
||||
continue
|
||||
is_visible = visibility.get(param_name, True)
|
||||
if param_name in advanced_params and not show_advanced:
|
||||
is_visible = False
|
||||
block.setVisible(is_visible)
|
||||
|
||||
# load_default_parameters: function definition for ScanSlicer behavior.
|
||||
def load_default_parameters(self):
|
||||
mode = self.params.load_defaults()
|
||||
self.sync_param_controls_from_model()
|
||||
self.set_preset_dropdown_custom()
|
||||
if mode == "saved":
|
||||
self.update_statusbar("Loaded saved defaults.")
|
||||
else:
|
||||
self.update_statusbar("Loaded factory defaults (no saved defaults found).")
|
||||
|
||||
# save_default_parameters: function definition for ScanSlicer behavior.
|
||||
def save_default_parameters(self):
|
||||
try:
|
||||
path = self.params.save_user_defaults()
|
||||
except OSError as exc:
|
||||
QMessageBox.critical(self, "Save defaults failed", str(exc))
|
||||
self.update_statusbar("Failed to save defaults.")
|
||||
return
|
||||
|
||||
self.update_statusbar("Saved defaults to " + path)
|
||||
|
||||
# autotune_parameters: function definition for ScanSlicer behavior.
|
||||
def autotune_parameters(self):
|
||||
if self.processing_busy:
|
||||
return
|
||||
if not self.autoslicer.image_loaded():
|
||||
QMessageBox.warning(self, "No image loaded", "Load an image first")
|
||||
return
|
||||
self._start_autotune_worker()
|
||||
|
||||
# clear_autotune_history: function definition for ScanSlicer behavior.
|
||||
def clear_autotune_history(self):
|
||||
if self.processing_busy:
|
||||
return
|
||||
|
||||
entry_count = len(self.autoslicer.feedback_entries)
|
||||
prompt = (
|
||||
"Clear auto-tune feedback history?\n\n"
|
||||
"This removes learned examples from previous saves and resets auto-tune learning."
|
||||
)
|
||||
if entry_count > 0:
|
||||
prompt += f"\n\nSaved examples: {entry_count}"
|
||||
|
||||
choice = QMessageBox.question(
|
||||
self,
|
||||
"Clear auto-tune history",
|
||||
prompt,
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if choice != QMessageBox.Yes:
|
||||
return
|
||||
|
||||
try:
|
||||
result = self.autoslicer.clear_feedback_entries()
|
||||
except OSError as exc:
|
||||
QMessageBox.critical(self, "Clear history failed", str(exc))
|
||||
self.update_statusbar("Failed to clear auto-tune history.")
|
||||
return
|
||||
|
||||
self.append_status_log(
|
||||
"Auto-tune feedback cleared: "
|
||||
+ f"entries={result['cleared_count']}, path={result['path']}, removed_file={result['removed_file']}"
|
||||
)
|
||||
self.update_statusbar("Auto-tune history cleared.")
|
||||
|
||||
# set_preset_dropdown_custom: function definition for ScanSlicer behavior.
|
||||
def set_preset_dropdown_custom(self):
|
||||
if self.preset_dropdown.currentText() == "Custom":
|
||||
return
|
||||
self.preset_dropdown.blockSignals(True)
|
||||
self.preset_dropdown.setCurrentText("Custom")
|
||||
self.preset_dropdown.blockSignals(False)
|
||||
|
||||
# refresh_preset_dropdown: function definition for ScanSlicer behavior.
|
||||
def refresh_preset_dropdown(self, selected_name=None):
|
||||
if selected_name is None:
|
||||
selected_name = self.preset_dropdown.currentText()
|
||||
|
||||
self.preset_dropdown.blockSignals(True)
|
||||
self.preset_dropdown.clear()
|
||||
self.preset_dropdown.addItem("Custom")
|
||||
self.preset_dropdown.addItems(self.params.preset_names())
|
||||
|
||||
if selected_name and self.preset_dropdown.findText(selected_name) >= 0:
|
||||
self.preset_dropdown.setCurrentText(selected_name)
|
||||
else:
|
||||
self.preset_dropdown.setCurrentText("Custom")
|
||||
self.preset_dropdown.blockSignals(False)
|
||||
|
||||
# save_current_as_preset: function definition for ScanSlicer behavior.
|
||||
def save_current_as_preset(self):
|
||||
if self.processing_busy:
|
||||
return
|
||||
|
||||
suggested_name = self.preset_dropdown.currentText()
|
||||
if suggested_name == "Custom":
|
||||
suggested_name = "My Preset"
|
||||
|
||||
preset_name, ok = QInputDialog.getText(
|
||||
self,
|
||||
"Save Preset",
|
||||
"Preset name:",
|
||||
text=suggested_name,
|
||||
)
|
||||
if not ok:
|
||||
return
|
||||
|
||||
preset_name = preset_name.strip()
|
||||
if len(preset_name) == 0:
|
||||
QMessageBox.warning(self, "Invalid preset name", "Preset name cannot be empty.")
|
||||
return
|
||||
|
||||
try:
|
||||
saved_name = self.params.save_named_preset(preset_name)
|
||||
except ValueError as exc:
|
||||
QMessageBox.warning(self, "Invalid preset name", str(exc))
|
||||
return
|
||||
except OSError as exc:
|
||||
QMessageBox.critical(self, "Save preset failed", str(exc))
|
||||
return
|
||||
|
||||
self.refresh_preset_dropdown(selected_name=saved_name)
|
||||
self.update_statusbar("Saved preset: " + saved_name)
|
||||
|
||||
# delete_current_preset: function definition for ScanSlicer behavior.
|
||||
def delete_current_preset(self):
|
||||
if self.processing_busy:
|
||||
return
|
||||
|
||||
preset_name = self.preset_dropdown.currentText().strip()
|
||||
if len(preset_name) == 0 or preset_name == "Custom":
|
||||
QMessageBox.warning(self, "No preset selected", "Select a user preset to delete.")
|
||||
return
|
||||
|
||||
choice = QMessageBox.question(
|
||||
self,
|
||||
"Delete Preset",
|
||||
f"Delete preset '{preset_name}'?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
QMessageBox.No,
|
||||
)
|
||||
if choice != QMessageBox.Yes:
|
||||
return
|
||||
|
||||
try:
|
||||
deleted_name = self.params.delete_named_preset(preset_name)
|
||||
except ValueError as exc:
|
||||
QMessageBox.warning(self, "Delete preset failed", str(exc))
|
||||
return
|
||||
except OSError as exc:
|
||||
QMessageBox.critical(self, "Delete preset failed", str(exc))
|
||||
return
|
||||
|
||||
self.refresh_preset_dropdown(selected_name="Custom")
|
||||
self.update_statusbar("Deleted preset: " + deleted_name)
|
||||
|
||||
# apply_parameter_preset: function definition for ScanSlicer behavior.
|
||||
def apply_parameter_preset(self, preset_name):
|
||||
if preset_name == "Custom":
|
||||
return
|
||||
if not self.params.apply_preset(preset_name):
|
||||
return
|
||||
self.sync_param_controls_from_model()
|
||||
self.preset_dropdown.blockSignals(True)
|
||||
self.preset_dropdown.setCurrentText(preset_name)
|
||||
self.preset_dropdown.blockSignals(False)
|
||||
self.update_statusbar("Applied preset: " + preset_name)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue