"""Splitter tab for extracting files from aggregated markdown."""
import os
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
QPushButton, QProgressBar, QFileDialog, QMessageBox
)
from PyQt6.QtCore import Qt, QCoreApplication
from core.splitter import Splitter
from core.exceptions import ObsidianToolException
class SplitterTab(QWidget):
"""Tab for splitting aggregated markdown files."""
def __init__(self):
"""Initialize the splitter tab."""
super().__init__()
self.splitter = Splitter()
self.init_ui()
def init_ui(self):
"""Initialize the user interface."""
layout = QVBoxLayout(self)
layout.setSpacing(15)
layout.setContentsMargins(20, 20, 20, 20)
# Aggregated File section
layout.addWidget(QLabel("Aggregated File:"))
file_layout = QHBoxLayout()
self.file_edit = QLineEdit()
self.file_edit.setReadOnly(True)
self.file_edit.setPlaceholderText("Select an aggregated .md file...")
file_layout.addWidget(self.file_edit)
self.file_btn = QPushButton("Browse...")
self.file_btn.setMaximumWidth(100)
self.file_btn.clicked.connect(self.browse_file)
file_layout.addWidget(self.file_btn)
layout.addLayout(file_layout)
# Output Directory section
layout.addWidget(QLabel("Output Directory:"))
output_layout = QHBoxLayout()
self.output_edit = QLineEdit()
self.output_edit.setReadOnly(True)
self.output_edit.setPlaceholderText("Select output directory...")
output_layout.addWidget(self.output_edit)
self.output_btn = QPushButton("Browse...")
self.output_btn.setMaximumWidth(100)
self.output_btn.clicked.connect(self.browse_output)
output_layout.addWidget(self.output_btn)
layout.addLayout(output_layout)
# Spacer
layout.addSpacing(20)
# Action button
self.split_btn = QPushButton("Split Files")
self.split_btn.setMinimumHeight(40)
self.split_btn.clicked.connect(self.split_files)
layout.addWidget(self.split_btn)
# Progress bar
self.progress_bar = QProgressBar()
self.progress_bar.setValue(0)
layout.addWidget(self.progress_bar)
# Status label
self.status_label = QLabel("Ready")
self.status_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.status_label.setStyleSheet("color: #666; font-style: italic;")
layout.addWidget(self.status_label)
# Add stretch to push everything to the top
layout.addStretch()
def browse_file(self):
"""Open dialog to select aggregated file."""
file_path, _ = QFileDialog.getOpenFileName(
self,
"Select Aggregated File",
os.path.expanduser("~"),
"Markdown Files (*.md);;All Files (*)"
)
if file_path:
self.file_edit.setText(file_path)
self.status_label.setText("Aggregated file selected")
def browse_output(self):
"""Open dialog to select output directory."""
directory = QFileDialog.getExistingDirectory(
self,
"Select Output Directory",
os.path.expanduser("~")
)
if directory:
self.output_edit.setText(directory)
self.status_label.setText("Output directory selected")
def split_files(self):
"""Perform the split operation."""
aggregated_file = self.file_edit.text()
output_dir = self.output_edit.text()
# Validate inputs
if not aggregated_file:
QMessageBox.warning(
self,
"Input Required",
"Please select an aggregated file."
)
return
if not output_dir:
QMessageBox.warning(
self,
"Input Required",
"Please select an output directory."
)
return
# Confirm if output directory is not empty
if os.path.exists(output_dir) and os.listdir(output_dir):
reply = QMessageBox.question(
self,
"Directory Not Empty",
"The output directory is not empty. Files may be overwritten.\n\n"
"Do you want to continue?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No
)
if reply == QMessageBox.StandardButton.No:
return
# Disable UI during operation
self.set_ui_enabled(False)
self.progress_bar.setValue(0)
self.status_label.setText("Splitting files...")
try:
# Progress callback
def update_progress(percentage, message):
self.progress_bar.setValue(percentage)
self.status_label.setText(message)
QCoreApplication.processEvents() # Keep UI responsive
# Perform split
result = self.splitter.split(
aggregated_file,
output_dir,
update_progress
)
# Show success message
QMessageBox.information(
self,
"Success",
f"Split complete!\n\n"
f"Files created: {result['files_created']}\n"
f"Directories created: {result['directories_created']}\n"
f"Output directory: {result['output_dir']}"
)
self.status_label.setText("Split completed successfully")
except ObsidianToolException as e:
QMessageBox.critical(
self,
"Error",
f"Split failed:\n\n{str(e)}"
)
self.status_label.setText("Split failed")
self.progress_bar.setValue(0)
except Exception as e:
QMessageBox.critical(
self,
"Unexpected Error",
f"An unexpected error occurred:\n\n{str(e)}"
)
self.status_label.setText("Split failed")
self.progress_bar.setValue(0)
finally:
# Re-enable UI
self.set_ui_enabled(True)
def set_ui_enabled(self, enabled: bool):
"""Enable or disable UI elements during operation."""
self.file_btn.setEnabled(enabled)
self.output_btn.setEnabled(enabled)
self.split_btn.setEnabled(enabled)