from PySide6.QtCore import QSize, Qt from PySide6.QtWidgets import ( QCheckBox, QComboBox, QGridLayout, QHBoxLayout, QLabel, QPushButton, QSpinBox, QWidget, ) from .ui_builders_shared import ScanSlicerUiSharedMixin, ScrollbarWheelOnlyScrollArea, icon_from_svg_data_url # ScanSlicerUiControlsMixin: class definition for ScanSlicer behavior. class ScanSlicerUiControlsMixin(ScanSlicerUiSharedMixin): # _add_directory_section: function definition for ScanSlicer behavior. def _add_directory_section(self, controls_layout, section_row): controls_layout.addWidget(self._build_section_title("Directory"), section_row, 0, 1, 2) section_row += 1 directory_group, directory_layout = self._new_group_layout() row = 0 self.button_opendir = self._create_panel_button("Open directory", self.open_directory) row = self._add_full_width_widget(directory_layout, row, self.button_opendir) row = self._add_spacer_row(directory_layout, row) row = self._add_label_row(directory_layout, row, "Output Directory") self.output_dir_label = QLabel("(not set)") self.output_dir_label.setWordWrap(True) row = self._add_full_width_widget(directory_layout, row, self.output_dir_label) row = self._add_spacer_row(directory_layout, row) self.button_set_outdir = self._create_panel_button("Set output directory", self.set_output_directory) row = self._add_full_width_widget(directory_layout, row, self.button_set_outdir) row = self._add_spacer_row(directory_layout, row) row = self._add_label_row(directory_layout, row, "Sort Images") self.sort_mode_dropdown = QComboBox() self.sort_mode_dropdown.addItems(["Name", "Time"]) self.sort_mode_dropdown.currentTextChanged.connect(self.set_sort_mode) row = self._add_full_width_widget(directory_layout, row, self.sort_mode_dropdown) controls_layout.addWidget(directory_group, section_row, 0, 1, 2) return section_row + 1 # _add_images_section: function definition for ScanSlicer behavior. def _add_images_section(self, controls_layout, section_row): controls_layout.addWidget(self._build_section_title("Images"), section_row, 0, 1, 2) section_row += 1 image_group, image_layout = self._new_group_layout() row = 0 navigation_row = QWidget(image_group) navigation_row_layout = QGridLayout(navigation_row) navigation_row_layout.setContentsMargins(0, 0, 0, 0) navigation_row_layout.setHorizontalSpacing(6) self.goto_image_dropdown = QComboBox(navigation_row) self.goto_image_dropdown.currentIndexChanged.connect(self.goto_image_from_dropdown) self.goto_image_dropdown.setEnabled(False) navigation_row_layout.addWidget(self.goto_image_dropdown, 0, 0) self.button_previmg = QPushButton(navigation_row) self.button_previmg.clicked.connect(self.prev_image) self.button_previmg.setToolTip("Previous image") prev_icon = icon_from_svg_data_url( self.PREV_IMAGE_ICON_DATA_URL, 20, palette=self.button_previmg.palette(), ) if prev_icon is not None: self.button_previmg.setIcon(prev_icon) self.button_previmg.setText("") self.button_previmg.setIconSize(QSize(20, 20)) else: self.button_previmg.setText("Prev") navigation_row_layout.addWidget(self.button_previmg, 0, 1) self.button_nextimg = QPushButton(navigation_row) self.button_nextimg.clicked.connect(self.next_image) self.button_nextimg.setToolTip("Next image") next_icon = icon_from_svg_data_url( self.NEXT_IMAGE_ICON_DATA_URL, 20, palette=self.button_nextimg.palette(), ) if next_icon is not None: self.button_nextimg.setIcon(next_icon) self.button_nextimg.setText("") self.button_nextimg.setIconSize(QSize(20, 20)) else: self.button_nextimg.setText("Next") navigation_row_layout.addWidget(self.button_nextimg, 0, 2) nav_button_height = max( self.button_previmg.sizeHint().height(), self.button_nextimg.sizeHint().height(), ) self.goto_image_dropdown.setFixedHeight(nav_button_height) navigation_row_layout.setColumnStretch(0, 1) row = self._add_full_width_widget(image_layout, row, navigation_row) row = self._add_spacer_row(image_layout, row) row = self._add_label_row(image_layout, row, "Save Format") self.save_format_dropdown = QComboBox() self.save_format_dropdown.addItems(["jpg", "png"]) self.save_format_dropdown.currentTextChanged.connect(self.set_save_format) row = self._add_full_width_widget(image_layout, row, self.save_format_dropdown) row = self._add_spacer_row(image_layout, row) self.jpg_quality_label = QLabel("JPG Quality (1-100)") row = self._add_full_width_widget(image_layout, row, self.jpg_quality_label) self.jpg_quality_spinbox = QSpinBox() self.jpg_quality_spinbox.setRange(1, 100) self.jpg_quality_spinbox.setSingleStep(1) self.jpg_quality_spinbox.setValue(self.jpg_quality) self.jpg_quality_spinbox.setFixedWidth(self.STEPPER_WIDTH) self.jpg_quality_spinbox.valueChanged.connect(self.set_jpg_quality) row = self._add_full_width_widget(image_layout, row, self.jpg_quality_spinbox) self.png_compression_label = QLabel("PNG Compression (0-9)") row = self._add_full_width_widget(image_layout, row, self.png_compression_label) self.png_compression_spinbox = QSpinBox() self.png_compression_spinbox.setRange(0, 9) self.png_compression_spinbox.setSingleStep(1) self.png_compression_spinbox.setValue(self.png_compression) self.png_compression_spinbox.setFixedWidth(self.STEPPER_WIDTH) self.png_compression_spinbox.valueChanged.connect(self.set_png_compression) row = self._add_full_width_widget(image_layout, row, self.png_compression_spinbox) self.save_format_dropdown.setCurrentText(self.save_format) row = self._add_spacer_row(image_layout, row) self.button_saveimgs = self._create_panel_button("Save images", self.save_all) row = self._add_full_width_widget(image_layout, row, self.button_saveimgs) controls_layout.addWidget(image_group, section_row, 0, 1, 2) return section_row + 1 # _add_presets_section: function definition for ScanSlicer behavior. def _add_presets_section(self, controls_layout, section_row): controls_layout.addWidget(self._build_section_title("Presets"), section_row, 0, 1, 2) section_row += 1 presets_group, presets_layout = self._new_group_layout() row = 0 autotune_row = QWidget(presets_group) autotune_row_layout = QHBoxLayout(autotune_row) autotune_row_layout.setContentsMargins(0, 0, 0, 0) autotune_row_layout.setSpacing(6) self.autotune_profile_dropdown = QComboBox(autotune_row) self.autotune_profile_dropdown.addItems(self.autoslicer.autotune_profile_names()) self.autotune_profile_dropdown.setToolTip("Auto-tune search profile") self.autotune_profile_dropdown.setCurrentText(self.autotune_profile) self.autotune_profile_dropdown.currentTextChanged.connect(self.set_autotune_profile) autotune_row_layout.addWidget(self.autotune_profile_dropdown, 1) self.button_autotune = self._create_panel_button("Auto-tune", self.autotune_parameters) autotune_row_layout.addWidget(self.button_autotune) row = self._add_full_width_widget(presets_layout, row, autotune_row) self.button_clear_autotune_history = self._create_panel_button( "Clear auto-tune history", self.clear_autotune_history, tooltip="Clear saved feedback used by auto-tune", ) row = self._add_full_width_widget(presets_layout, row, self.button_clear_autotune_history) row = self._add_spacer_row(presets_layout, row) expected_block = self._build_parameter_block( presets_group, "expected_count", self.params.expected_count, ) row = self._add_full_width_widget(presets_layout, row, expected_block) row = self._add_spacer_row(presets_layout, row) row = self._add_label_row(presets_layout, row, "Preset") self.preset_dropdown = QComboBox() self.preset_dropdown.addItem("Custom") self.preset_dropdown.addItems(self.params.preset_names()) self.preset_dropdown.currentTextChanged.connect(self.apply_parameter_preset) row = self._add_full_width_widget(presets_layout, row, self.preset_dropdown) self.button_delete_preset = self._create_panel_button("Delete current preset", self.delete_current_preset) row = self._add_full_width_widget(presets_layout, row, self.button_delete_preset) controls_layout.addWidget(presets_group, section_row, 0, 1, 2) return section_row + 1 # _add_parameters_section: function definition for ScanSlicer behavior. def _add_parameters_section(self, controls_layout, section_row): controls_layout.addWidget(self._build_section_title("Parameters"), section_row, 0, 1, 2) section_row += 1 parameters_group, parameters_layout = self._new_group_layout() row = 0 self.button_loaddef = self._create_panel_button("Load defaults", self.load_default_parameters) row = self._add_full_width_widget(parameters_layout, row, self.button_loaddef) self.button_savedef = self._create_panel_button("Save new defaults", self.save_default_parameters) row = self._add_full_width_widget(parameters_layout, row, self.button_savedef) self.button_savepreset = self._create_panel_button("Save as preset...", self.save_current_as_preset) row = self._add_full_width_widget(parameters_layout, row, self.button_savepreset) row = self._add_spacer_row(parameters_layout, row) self.show_advanced_checkbox = QCheckBox("Show advanced parameters") self.show_advanced_checkbox.setChecked(self.show_advanced_params) self.show_advanced_checkbox.toggled.connect(self.set_show_advanced_parameters) row = self._add_full_width_widget(parameters_layout, row, self.show_advanced_checkbox) row = self._add_spacer_row(parameters_layout, row) for name, parameter in self.params.items(): if name == "expected_count": continue param_block = self._build_parameter_block(parameters_group, name, parameter) row = self._add_full_width_widget(parameters_layout, row, param_block) controls_layout.addWidget(parameters_group, section_row, 0, 1, 2) return section_row + 1 # _build_controls_panel: function definition for ScanSlicer behavior. def _build_controls_panel(self, root): controls = QWidget() controls_layout = QGridLayout(controls) section_row = 0 section_row = self._add_directory_section(controls_layout, section_row) section_row = self._add_images_section(controls_layout, section_row) section_row = self._add_presets_section(controls_layout, section_row) section_row = self._add_parameters_section(controls_layout, section_row) controls_layout.setRowStretch(section_row + 1, 1) controls_scroll = ScrollbarWheelOnlyScrollArea(root) controls_scroll.setWidgetResizable(True) controls_scroll.setWidget(controls) controls_scroll.setFixedWidth(self.CONTROL_PANEL_WIDTH) controls_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) return controls_scroll