diff --git a/scripts/advanced_tab.py b/scripts/advanced_tab.py new file mode 100644 index 0000000000000000000000000000000000000000..85617ddda6d7d7060fbcb257791487574458d39f --- /dev/null +++ b/scripts/advanced_tab.py @@ -0,0 +1,97 @@ +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QGroupBox, QScrollArea) +from PyQt6.QtCore import Qt +import os +import sys + +# Import utilities from debug_tool +from debug_tool.utils.qt_widgets import (create_group_with_text, create_button_layout, + create_info_group, create_preview_group) +from debug_tool.utils.file_handlers import select_file, clean_directory, copy_file, run_command +from debug_tool.utils.image_handlers import update_preview + +class AdvancedTab(QWidget): + def __init__(self, config_reader): + super().__init__() + self.config_reader = config_reader + + # Initialize paths + self.mono_depth_dir = self.config_reader.directories['monoDepthDir'] + self.edge_net_dir = self.config_reader.directories['edgeNetDir'] + self.material_dir = self.config_reader.directories['materialRecogDir'] + + self.setup_ui() + + def setup_ui(self): + # Create main layout + main_layout = QVBoxLayout(self) + + # Create scroll area for module controls + scroll = QScrollArea() + scroll.setWidgetResizable(True) + scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + + # Container for module controls + container = QWidget() + container_layout = QVBoxLayout(container) + + # Add module control groups + self.add_module_controls(container_layout) + + scroll.setWidget(container) + main_layout.addWidget(scroll) + + def add_module_controls(self, layout): + # Status section for overall progress + status_group, self.status_text = create_group_with_text("Pipeline Status", 100) + layout.addWidget(status_group) + + # Image Shifter Controls + shifter_group = QGroupBox("Image Shifter") + shifter_layout = QVBoxLayout(shifter_group) + # Add shifter specific controls + layout.addWidget(shifter_group) + + # Depth Estimation Controls + depth_group = QGroupBox("Depth Estimation") + depth_layout = QVBoxLayout(depth_group) + # Add depth estimation specific controls + layout.addWidget(depth_group) + + # Material Recognition Controls + material_group = QGroupBox("Material Recognition") + material_layout = QVBoxLayout(material_group) + # Add material recognition specific controls + layout.addWidget(material_group) + + # EdgeNet Controls + edgenet_group = QGroupBox("EdgeNet") + edgenet_layout = QVBoxLayout(edgenet_group) + # Add EdgeNet specific controls + layout.addWidget(edgenet_group) + + # Mesh Processing Controls + mesh_group = QGroupBox("Mesh Processing") + mesh_layout = QVBoxLayout(mesh_group) + # Add mesh processing specific controls + layout.addWidget(mesh_group) + + # Preview section + preview_group = QGroupBox("Preview") + preview_layout = QHBoxLayout(preview_group) + + input_group, self.input_preview = create_preview_group("Input") + output_group, self.output_preview = create_preview_group("Output") + + preview_layout.addWidget(input_group) + preview_layout.addWidget(output_group) + layout.addWidget(preview_group) + + # Add some spacing at the bottom + layout.addStretch() + + def update_status(self, message): + self.status_text.append(message) + # Scroll to bottom + scrollbar = self.status_text.verticalScrollBar() + scrollbar.setValue(scrollbar.maximum()) \ No newline at end of file diff --git a/scripts/simple_tab.py b/scripts/simple_tab.py new file mode 100644 index 0000000000000000000000000000000000000000..e415700164cd0768ae151843186be53567fb0761 --- /dev/null +++ b/scripts/simple_tab.py @@ -0,0 +1,200 @@ +from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, + QGroupBox, QCheckBox, QMessageBox, QPushButton) +from PyQt6.QtCore import Qt, QThread, pyqtSignal +import os +import sys + +# Import utilities from debug_tool +from debug_tool.utils.qt_widgets import (create_group_with_text, create_button_layout, + create_info_group, create_preview_group) +from debug_tool.utils.file_handlers import select_file, clean_directory, copy_file, run_command +from debug_tool.utils.image_handlers import update_preview + +# Import existing module implementations +from debug_tool.tabs.shifter_tab import ShifterTab +from debug_tool.tabs.depth_tab import DepthTab +from debug_tool.tabs.material_tab import MaterialTab +from debug_tool.tabs.edge_net_tab import EdgeNetTab + +class PipelineWorker(QThread): + progress = pyqtSignal(str) + finished = pyqtSignal(bool, str) + + def __init__(self, tab_instance): + super().__init__() + self.tab = tab_instance + + def run(self): + try: + self.run_pipeline() + self.finished.emit(True, "Pipeline completed successfully!") + except Exception as e: + self.finished.emit(False, f"Pipeline failed: {str(e)}") + + def run_pipeline(self): + steps = [ + (self.tab.shift_image, "Shifting input image..."), + (self.tab.run_depth_estimation, "Running depth estimation..."), + (self.tab.run_material_recognition, "Running material recognition..."), + (self.tab.run_edge_net, "Running EdgeNet..."), + (self.tab.run_mesh_splitting, "Running mesh splitting..."), + (self.tab.run_blender_flip, "Running Blender flip...") + ] + + for step_func, message in steps: + self.progress.emit(message) + step_func() + +class SimpleTab(QWidget): + def __init__(self, config_reader): + super().__init__() + self.config_reader = config_reader + self.input_path = None + self.pipeline_thread = None + + # Initialize module instances + self.shifter = ShifterTab(self.config_reader) + self.depth = DepthTab(self.config_reader) + self.material = MaterialTab(self.config_reader) + self.edge_net = EdgeNetTab(self.config_reader) + + # Hide their UIs as we'll use our own + self.shifter.hide() + self.depth.hide() + self.material.hide() + self.edge_net.hide() + + self.setup_ui() + + def setup_ui(self): + layout = QVBoxLayout(self) + + # Controls section + controls_group = QGroupBox("Pipeline Controls") + controls_layout = QVBoxLayout(controls_group) + + # Info display + info_rows = [ + ("Input Image:", "No file selected"), + ("Status:", "Ready") + ] + self.info_group, self.info_labels = create_info_group("Information", info_rows) + controls_layout.addWidget(self.info_group) + + # Options + options_layout = QHBoxLayout() + + self.auto_depth_check = QCheckBox("Auto Generate Depth Map") + self.auto_depth_check.setChecked(True) + options_layout.addWidget(self.auto_depth_check) + + self.include_top_check = QCheckBox("Include Top in Mesh") + options_layout.addWidget(self.include_top_check) + + self.shift_image_check = QCheckBox("Shift Input Image") + options_layout.addWidget(self.shift_image_check) + + controls_layout.addLayout(options_layout) + + # Buttons + buttons = [ + ("Select Input Image", self.handle_file_select, 'left'), + ("Run Pipeline", self.run_full_pipeline, 'right') + ] + controls_layout.addLayout(create_button_layout(*buttons)) + + layout.addWidget(controls_group) + + # Status section + status_group, self.status_text = create_group_with_text("Pipeline Status", 150) + layout.addWidget(status_group) + + # Preview section + preview_group = QGroupBox("Preview") + preview_layout = QHBoxLayout(preview_group) + + input_group, self.input_preview = create_preview_group("Input Image") + output_group, self.output_preview = create_preview_group("Current Output") + + preview_layout.addWidget(input_group) + preview_layout.addWidget(output_group) + layout.addWidget(preview_group) + + def handle_file_select(self): + file_path = select_file( + self, + "Select Input Image", + "Images (*.png *.jpg *.jpeg)" + ) + + if file_path: + self.input_path = file_path + self.info_labels["Input Image:"].setText(os.path.basename(file_path)) + self.update_status(f"Selected input file: {file_path}") + update_preview(self.input_preview, file_path, + error_callback=self.update_status) + + # Provide input path to all modules + self.shifter.depth_input_path = file_path + self.depth.depth_input_path = file_path + self.material.input_path = file_path + self.edge_net.input_path = file_path + + def run_full_pipeline(self): + if not self.input_path: + QMessageBox.warning(self, "Warning", "Please select an input file first") + return + + if self.pipeline_thread and self.pipeline_thread.isRunning(): + QMessageBox.warning(self, "Warning", "Pipeline is already running") + return + + self.pipeline_thread = PipelineWorker(self) + self.pipeline_thread.progress.connect(self.update_status) + self.pipeline_thread.finished.connect(self.pipeline_completed) + self.pipeline_thread.start() + + # Disable controls while running + self.setEnabled(False) + + def pipeline_completed(self, success, message): + self.setEnabled(True) + self.update_status(message) + + if success: + QMessageBox.information(self, "Success", "Pipeline completed successfully!") + else: + QMessageBox.critical(self, "Error", f"Pipeline failed: {message}") + + def update_status(self, message): + self.status_text.append(message) + self.info_labels["Status:"].setText(message.split("...")[-1] if "..." in message else message) + # Scroll to bottom + scrollbar = self.status_text.verticalScrollBar() + scrollbar.setValue(scrollbar.maximum()) + + # Pipeline steps using existing module implementations + def shift_image(self): + if not self.shift_image_check.isChecked(): + self.update_status("Skipping image shift...") + return + self.shifter.run_shifter() + + def run_depth_estimation(self): + if not self.auto_depth_check.isChecked(): + self.update_status("Skipping depth estimation - manual depth selected") + return + self.depth.run_depth_estimation() + + def run_material_recognition(self): + self.material.run_material_recognition() + + def run_edge_net(self): + self.edge_net.include_top = self.include_top_check.isChecked() + self.edge_net.run_edge_net() + + def run_mesh_splitting(self): + self.edge_net.run_mesh_splitting() + + def run_blender_flip(self): + self.edge_net.run_blender_flip() \ No newline at end of file