"""Dialog and worker to import TIFF folders, generate INI, and convert to H5."""
from PyQt6.QtWidgets import (
QDialog,
QLabel,
QLineEdit,
QPushButton,
QVBoxLayout,
QHBoxLayout,
QFileDialog,
QTextEdit,
QComboBox,
QMessageBox,
QProgressBar,
QGroupBox,
QFormLayout
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
import os
from coseda.io import get_dir_size, get_free_space_windows, get_free_space_unix, handle_input, parse_config
from coseda.logging_utils import log_start, log_result
[docs]
class ImportTiffWindow(QDialog):
"""UI to select a TIFF folder, set compression, and launch conversion to H5/INI."""
def __init__(self, parent=None):
"""Dialog to import TIFF folders, convert to H5/INI, and optionally add to the workspace."""
super().__init__(parent)
self.parent = parent # Reference to main window
self.setWindowTitle("Import TIFF")
self.setMinimumSize(500, 400)
self.setWindowFlags(Qt.WindowType.Window)
self.init_ui()
[docs]
def init_ui(self):
"""Build the UI controls for selecting a folder and setting TIFF conversion options."""
main_layout = QVBoxLayout()
main_layout.setSpacing(10)
main_layout.setContentsMargins(10, 10, 10, 10)
# Folder selection
folder_group = QGroupBox("TIFF Folder")
folder_layout = QHBoxLayout()
self.folder_line_edit = QLineEdit()
browse_button = QPushButton("Browse")
browse_button.clicked.connect(self.select_tiff_folder)
folder_layout.addWidget(self.folder_line_edit)
folder_layout.addWidget(browse_button)
folder_group.setLayout(folder_layout)
main_layout.addWidget(folder_group)
# Parameters
params_group = QGroupBox("Conversion Parameters")
params_layout = QFormLayout()
self.compression_combo = QComboBox()
self.compression_combo.addItems(["None", "gzip", "lzf"])
self.compression_combo.setCurrentText("None")
self.compression_level_line_edit = QLineEdit("4") # Default to 4
params_layout.addRow(QLabel("Compression:"), self.compression_combo)
params_layout.addRow(QLabel("Compression Level:"), self.compression_level_line_edit)
params_group.setLayout(params_layout)
main_layout.addWidget(params_group)
# Buttons
buttons_layout = QHBoxLayout()
self.import_button = QPushButton("Import")
self.import_button.clicked.connect(self.start_import)
cancel_button = QPushButton("Close")
cancel_button.clicked.connect(self.close)
buttons_layout.addStretch()
buttons_layout.addWidget(self.import_button)
buttons_layout.addWidget(cancel_button)
main_layout.addLayout(buttons_layout)
# Status Text
self.status_text_edit = QTextEdit()
self.status_text_edit.setReadOnly(True)
main_layout.addWidget(self.status_text_edit)
self.setLayout(main_layout)
[docs]
def select_tiff_folder(self):
"""Prompt the user to choose a TIFF folder and update the input field."""
folder = QFileDialog.getExistingDirectory(self, "Select TIFF Folder", os.getcwd())
if folder:
self.folder_line_edit.setText(folder)
[docs]
def start_import(self):
"""Validate input, start the TIFF import worker, and wire up status callbacks."""
# Get the folder path
folder_path = self.folder_line_edit.text()
if not os.path.isdir(folder_path):
QMessageBox.warning(self, "Invalid Folder", "Please select a valid folder containing TIFF files.")
return
# Get parameters
compression = self.compression_combo.currentText()
if compression == "None":
compression = None
compression_level_text = self.compression_level_line_edit.text()
if compression_level_text:
try:
compression_level = int(compression_level_text)
except ValueError:
QMessageBox.warning(self, "Invalid Compression Level", "Please enter a valid integer for compression level.")
return
else:
compression_level = None # Default value
# Start the import process
self.import_button.setEnabled(False)
self.status_text_edit.clear()
self.update_status("Starting import...")
# Use QThread to run the import process in a separate thread
self.import_thread = TiffImportThread(
folder_path,
compression,
compression_level,
parent=self
)
self.import_thread.status_update.connect(self.update_status)
self.import_thread.finished.connect(self.import_finished)
self.import_thread.start()
[docs]
def update_status(self, message):
"""Append a status line to the log text box."""
self.status_text_edit.append(message)
[docs]
def import_finished(self, success, message):
"""Handle completion, surface result, and auto-add generated INI to the workspace."""
if success:
self.update_status("Import completed successfully.")
QMessageBox.information(self, "Import Complete", "TIFF files have been successfully imported.")
else:
self.update_status(f"Import failed: {message}")
QMessageBox.critical(self, "Import Failed", f"Import failed: {message}")
ini_file_path = getattr(self.import_thread, "ini_file_path", None)
if ini_file_path and self.parent and hasattr(self.parent, "add_generated_ini_paths"):
result = self.parent.add_generated_ini_paths([ini_file_path])
if result["added"]:
self.update_status(f"Added to workspace: {result['added'][0]}")
self.import_button.setEnabled(True)
[docs]
class TiffImportThread(QThread):
status_update = pyqtSignal(str)
finished = pyqtSignal(bool, str)
def __init__(self, folder_path, compression, compression_level, parent=None):
"""Background worker that creates an INI and converts TIFFs to H5 without blocking the UI."""
super().__init__(parent)
self.folder_path = folder_path
self.compression = compression
self.compression_level = compression_level
self.parent = parent
[docs]
def run(self):
"""Execute TIFF import and conversion, emitting progress and final status."""
try:
from coseda.importers.import_tiff import (
create_insfiles_tiff,
set_tiffconversion_parameters,
tiff_conversion
)
# Create the INI file
self.status_update.emit("Creating INI file...")
success, ini_file_path = create_insfiles_tiff(self.folder_path, target=None)
if not success:
self.status_update.emit("Failed to create INI file.")
self.finished.emit(False, "Failed to create INI file.")
return
self.ini_file_path = ini_file_path
self.status_update.emit(f"INI file created at {ini_file_path}")
# Set TIFF conversion parameters
self.status_update.emit("Setting TIFF conversion parameters...")
set_tiffconversion_parameters(ini_file_path, compression=self.compression, compression_level=self.compression_level)
self.status_update.emit("TIFF conversion parameters set.")
# Perform the TIFF conversion
self.status_update.emit("Starting TIFF conversion...")
tiff_conversion(ini_file_path)
self.status_update.emit("TIFF conversion completed.")
# Signal success
self.finished.emit(True, "")
except Exception as e:
self.status_update.emit(f"Error: {str(e)}")
self.finished.emit(False, str(e))