diff --git a/scanslicer/ui_builders_controls.py b/scanslicer/ui_builders_controls.py index ab25a46..39c8217 100644 --- a/scanslicer/ui_builders_controls.py +++ b/scanslicer/ui_builders_controls.py @@ -14,3 +14,234 @@ from .ui_builders_shared import ScanSlicerUiSharedMixin, ScrollbarWheelOnlyScrol # 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