Basic TL working
This commit is contained in:
parent
e7b41c9f44
commit
5fd0ae7caf
3 changed files with 601 additions and 877 deletions
|
|
@ -1,466 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
File Manager Tab for DazedMTLTool GUI
|
||||
|
||||
Manages input files from 'files' directory and output to 'translated' directory.
|
||||
Users can add files through GUI or by copying them to the files folder.
|
||||
"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from PyQt5.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QTreeWidget, QTreeWidgetItem,
|
||||
QPushButton, QGroupBox, QSplitter, QTextEdit, QFileDialog, QMessageBox,
|
||||
QProgressBar, QFrame, QHeaderView
|
||||
)
|
||||
from PyQt5.QtCore import Qt, QTimer
|
||||
from PyQt5.QtGui import QFont
|
||||
|
||||
|
||||
class FileManagerTab(QWidget):
|
||||
"""File Manager tab for managing input and output files."""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent)
|
||||
self.project_root = Path(__file__).parent.parent
|
||||
self.files_dir = self.project_root / "files"
|
||||
self.translated_dir = self.project_root / "translated"
|
||||
|
||||
# Ensure directories exist
|
||||
self.files_dir.mkdir(exist_ok=True)
|
||||
self.translated_dir.mkdir(exist_ok=True)
|
||||
|
||||
self.setup_ui()
|
||||
self.refresh_file_lists()
|
||||
|
||||
# Auto-refresh timer
|
||||
self.refresh_timer = QTimer()
|
||||
self.refresh_timer.timeout.connect(self.refresh_file_lists)
|
||||
self.refresh_timer.start(3000) # Refresh every 3 seconds
|
||||
|
||||
def setup_ui(self):
|
||||
"""Set up the user interface."""
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# Title
|
||||
title_label = QLabel("File Manager")
|
||||
title_label.setStyleSheet("font-size: 16px; font-weight: bold; color: #007acc;")
|
||||
layout.addWidget(title_label)
|
||||
|
||||
# Description
|
||||
desc_label = QLabel(
|
||||
"Input files are loaded from the 'files' directory. "
|
||||
"Translated files will be saved to the 'translated' directory. "
|
||||
"You can add files using the GUI or by copying them to the files folder."
|
||||
)
|
||||
desc_label.setWordWrap(True)
|
||||
desc_label.setStyleSheet("color: #cccccc; margin-bottom: 10px;")
|
||||
layout.addWidget(desc_label)
|
||||
|
||||
# Main splitter
|
||||
splitter = QSplitter(Qt.Horizontal)
|
||||
|
||||
# Input files section
|
||||
input_group = self.create_input_files_section()
|
||||
splitter.addWidget(input_group)
|
||||
|
||||
# Output files section
|
||||
output_group = self.create_output_files_section()
|
||||
splitter.addWidget(output_group)
|
||||
|
||||
# Set equal sizes
|
||||
splitter.setSizes([400, 400])
|
||||
layout.addWidget(splitter)
|
||||
|
||||
# Action buttons
|
||||
button_layout = self.create_action_buttons()
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
# Status bar
|
||||
self.status_label = QLabel("Ready")
|
||||
self.status_label.setStyleSheet("color: #cccccc; padding: 5px;")
|
||||
layout.addWidget(self.status_label)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def create_input_files_section(self):
|
||||
"""Create the input files section."""
|
||||
group = QGroupBox("Input Files (files directory)")
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# File tree
|
||||
self.input_tree = QTreeWidget()
|
||||
self.input_tree.setHeaderLabels(["Filename", "Size", "Modified"])
|
||||
self.input_tree.header().setSectionResizeMode(0, QHeaderView.Stretch)
|
||||
self.input_tree.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
|
||||
self.input_tree.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
|
||||
self.input_tree.itemSelectionChanged.connect(self.on_input_file_selected)
|
||||
layout.addWidget(self.input_tree)
|
||||
|
||||
# Input buttons
|
||||
input_button_layout = QHBoxLayout()
|
||||
|
||||
self.add_file_btn = QPushButton("Add Files")
|
||||
self.add_file_btn.clicked.connect(self.add_files)
|
||||
input_button_layout.addWidget(self.add_file_btn)
|
||||
|
||||
self.remove_file_btn = QPushButton("Remove Selected")
|
||||
self.remove_file_btn.clicked.connect(self.remove_input_file)
|
||||
self.remove_file_btn.setEnabled(False)
|
||||
input_button_layout.addWidget(self.remove_file_btn)
|
||||
|
||||
self.open_files_folder_btn = QPushButton("Open Files Folder")
|
||||
self.open_files_folder_btn.clicked.connect(self.open_files_folder)
|
||||
input_button_layout.addWidget(self.open_files_folder_btn)
|
||||
|
||||
input_button_layout.addStretch()
|
||||
layout.addLayout(input_button_layout)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
|
||||
def create_output_files_section(self):
|
||||
"""Create the output files section."""
|
||||
group = QGroupBox("Output Files (translated directory)")
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# File tree
|
||||
self.output_tree = QTreeWidget()
|
||||
self.output_tree.setHeaderLabels(["Filename", "Size", "Modified"])
|
||||
self.output_tree.header().setSectionResizeMode(0, QHeaderView.Stretch)
|
||||
self.output_tree.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
|
||||
self.output_tree.header().setSectionResizeMode(2, QHeaderView.ResizeToContents)
|
||||
self.output_tree.itemSelectionChanged.connect(self.on_output_file_selected)
|
||||
layout.addWidget(self.output_tree)
|
||||
|
||||
# Output buttons
|
||||
output_button_layout = QHBoxLayout()
|
||||
|
||||
self.view_output_btn = QPushButton("View Selected")
|
||||
self.view_output_btn.clicked.connect(self.view_output_file)
|
||||
self.view_output_btn.setEnabled(False)
|
||||
output_button_layout.addWidget(self.view_output_btn)
|
||||
|
||||
self.delete_output_btn = QPushButton("Delete Selected")
|
||||
self.delete_output_btn.clicked.connect(self.delete_output_file)
|
||||
self.delete_output_btn.setEnabled(False)
|
||||
output_button_layout.addWidget(self.delete_output_btn)
|
||||
|
||||
self.open_translated_folder_btn = QPushButton("Open Translated Folder")
|
||||
self.open_translated_folder_btn.clicked.connect(self.open_translated_folder)
|
||||
output_button_layout.addWidget(self.open_translated_folder_btn)
|
||||
|
||||
output_button_layout.addStretch()
|
||||
layout.addLayout(output_button_layout)
|
||||
|
||||
group.setLayout(layout)
|
||||
return group
|
||||
|
||||
def create_action_buttons(self):
|
||||
"""Create main action buttons."""
|
||||
layout = QHBoxLayout()
|
||||
|
||||
self.refresh_btn = QPushButton("Refresh File Lists")
|
||||
self.refresh_btn.clicked.connect(self.refresh_file_lists)
|
||||
layout.addWidget(self.refresh_btn)
|
||||
|
||||
self.clear_translated_btn = QPushButton("Clear All Translated Files")
|
||||
self.clear_translated_btn.clicked.connect(self.clear_translated_files)
|
||||
layout.addWidget(self.clear_translated_btn)
|
||||
|
||||
layout.addStretch()
|
||||
|
||||
# Auto-refresh indicator
|
||||
self.auto_refresh_label = QLabel("Auto-refresh: ON")
|
||||
self.auto_refresh_label.setStyleSheet("color: #00aa00; font-size: 10px;")
|
||||
layout.addWidget(self.auto_refresh_label)
|
||||
|
||||
return layout
|
||||
|
||||
def refresh_file_lists(self):
|
||||
"""Refresh both input and output file lists."""
|
||||
self.refresh_input_files()
|
||||
self.refresh_output_files()
|
||||
self.update_status()
|
||||
|
||||
def refresh_input_files(self):
|
||||
"""Refresh the input files tree."""
|
||||
self.input_tree.clear()
|
||||
|
||||
if not self.files_dir.exists():
|
||||
return
|
||||
|
||||
supported_extensions = {'.json', '.txt', '.csv', '.js', '.py', '.xml', '.html', '.md'}
|
||||
|
||||
for file_path in self.files_dir.iterdir():
|
||||
if (file_path.is_file() and
|
||||
file_path.suffix.lower() in supported_extensions and
|
||||
file_path.name != '.gitkeep'):
|
||||
item = QTreeWidgetItem()
|
||||
item.setText(0, file_path.name)
|
||||
|
||||
# File size
|
||||
size = file_path.stat().st_size
|
||||
if size < 1024:
|
||||
size_str = f"{size} B"
|
||||
elif size < 1024 * 1024:
|
||||
size_str = f"{size / 1024:.1f} KB"
|
||||
else:
|
||||
size_str = f"{size / (1024 * 1024):.1f} MB"
|
||||
item.setText(1, size_str)
|
||||
|
||||
# Modified time
|
||||
import datetime
|
||||
mtime = datetime.datetime.fromtimestamp(file_path.stat().st_mtime)
|
||||
item.setText(2, mtime.strftime("%Y-%m-%d %H:%M"))
|
||||
|
||||
# Store file path
|
||||
item.setData(0, Qt.UserRole, str(file_path))
|
||||
|
||||
self.input_tree.addTopLevelItem(item)
|
||||
|
||||
def refresh_output_files(self):
|
||||
"""Refresh the output files tree."""
|
||||
self.output_tree.clear()
|
||||
|
||||
if not self.translated_dir.exists():
|
||||
return
|
||||
|
||||
for file_path in self.translated_dir.iterdir():
|
||||
if file_path.is_file() and file_path.name != '.gitkeep':
|
||||
item = QTreeWidgetItem()
|
||||
item.setText(0, file_path.name)
|
||||
|
||||
# File size
|
||||
size = file_path.stat().st_size
|
||||
if size < 1024:
|
||||
size_str = f"{size} B"
|
||||
elif size < 1024 * 1024:
|
||||
size_str = f"{size / 1024:.1f} KB"
|
||||
else:
|
||||
size_str = f"{size / (1024 * 1024):.1f} MB"
|
||||
item.setText(1, size_str)
|
||||
|
||||
# Modified time
|
||||
import datetime
|
||||
mtime = datetime.datetime.fromtimestamp(file_path.stat().st_mtime)
|
||||
item.setText(2, mtime.strftime("%Y-%m-%d %H:%M"))
|
||||
|
||||
# Store file path
|
||||
item.setData(0, Qt.UserRole, str(file_path))
|
||||
|
||||
self.output_tree.addTopLevelItem(item)
|
||||
|
||||
def update_status(self):
|
||||
"""Update the status label."""
|
||||
input_count = self.input_tree.topLevelItemCount()
|
||||
output_count = self.output_tree.topLevelItemCount()
|
||||
self.status_label.setText(f"Input files: {input_count} | Output files: {output_count}")
|
||||
|
||||
def on_input_file_selected(self):
|
||||
"""Handle input file selection."""
|
||||
selected = self.input_tree.selectedItems()
|
||||
self.remove_file_btn.setEnabled(len(selected) > 0)
|
||||
|
||||
def on_output_file_selected(self):
|
||||
"""Handle output file selection."""
|
||||
selected = self.output_tree.selectedItems()
|
||||
self.view_output_btn.setEnabled(len(selected) > 0)
|
||||
self.delete_output_btn.setEnabled(len(selected) > 0)
|
||||
|
||||
def add_files(self):
|
||||
"""Add files to the input directory."""
|
||||
file_paths, _ = QFileDialog.getOpenFileNames(
|
||||
self,
|
||||
"Select Files to Add",
|
||||
"",
|
||||
"All Supported Files (*.json *.txt *.csv *.js *.py *.xml *.html *.md);;All Files (*.*)"
|
||||
)
|
||||
|
||||
if not file_paths:
|
||||
return
|
||||
|
||||
copied_count = 0
|
||||
for file_path in file_paths:
|
||||
source_path = Path(file_path)
|
||||
dest_path = self.files_dir / source_path.name
|
||||
|
||||
try:
|
||||
# Check if file already exists
|
||||
if dest_path.exists():
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"File Exists",
|
||||
f"'{source_path.name}' already exists. Overwrite?",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
if reply != QMessageBox.Yes:
|
||||
continue
|
||||
|
||||
shutil.copy2(source_path, dest_path)
|
||||
copied_count += 1
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(
|
||||
self,
|
||||
"Copy Error",
|
||||
f"Failed to copy '{source_path.name}':\n{str(e)}"
|
||||
)
|
||||
|
||||
if copied_count > 0:
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Files Added",
|
||||
f"Successfully added {copied_count} file(s) to the input directory."
|
||||
)
|
||||
self.refresh_input_files()
|
||||
|
||||
def remove_input_file(self):
|
||||
"""Remove selected input file."""
|
||||
selected = self.input_tree.selectedItems()
|
||||
if not selected:
|
||||
return
|
||||
|
||||
item = selected[0]
|
||||
file_path = Path(item.data(0, Qt.UserRole))
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Confirm Removal",
|
||||
f"Are you sure you want to remove '{file_path.name}' from the input directory?",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
try:
|
||||
file_path.unlink()
|
||||
self.refresh_input_files()
|
||||
QMessageBox.information(self, "File Removed", f"'{file_path.name}' has been removed.")
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to remove file:\n{str(e)}")
|
||||
|
||||
def view_output_file(self):
|
||||
"""View selected output file."""
|
||||
selected = self.output_tree.selectedItems()
|
||||
if not selected:
|
||||
return
|
||||
|
||||
item = selected[0]
|
||||
file_path = Path(item.data(0, Qt.UserRole))
|
||||
|
||||
try:
|
||||
# Open file with default system application
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
os.startfile(str(file_path))
|
||||
elif platform.system() == 'Darwin': # macOS
|
||||
subprocess.run(['open', str(file_path)])
|
||||
else: # Linux
|
||||
subprocess.run(['xdg-open', str(file_path)])
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to open file:\n{str(e)}")
|
||||
|
||||
def delete_output_file(self):
|
||||
"""Delete selected output file."""
|
||||
selected = self.output_tree.selectedItems()
|
||||
if not selected:
|
||||
return
|
||||
|
||||
item = selected[0]
|
||||
file_path = Path(item.data(0, Qt.UserRole))
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Confirm Deletion",
|
||||
f"Are you sure you want to delete '{file_path.name}' from the output directory?",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
try:
|
||||
file_path.unlink()
|
||||
self.refresh_output_files()
|
||||
QMessageBox.information(self, "File Deleted", f"'{file_path.name}' has been deleted.")
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to delete file:\n{str(e)}")
|
||||
|
||||
def clear_translated_files(self):
|
||||
"""Clear all files from the translated directory."""
|
||||
if self.output_tree.topLevelItemCount() == 0:
|
||||
QMessageBox.information(self, "No Files", "There are no files to clear.")
|
||||
return
|
||||
|
||||
reply = QMessageBox.question(
|
||||
self,
|
||||
"Confirm Clear All",
|
||||
"Are you sure you want to delete ALL files from the translated directory?",
|
||||
QMessageBox.Yes | QMessageBox.No
|
||||
)
|
||||
|
||||
if reply == QMessageBox.Yes:
|
||||
try:
|
||||
deleted_count = 0
|
||||
for file_path in self.translated_dir.iterdir():
|
||||
if file_path.is_file() and file_path.name != '.gitkeep':
|
||||
file_path.unlink()
|
||||
deleted_count += 1
|
||||
|
||||
self.refresh_output_files()
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"Files Cleared",
|
||||
f"Successfully deleted {deleted_count} file(s) from the translated directory."
|
||||
)
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to clear files:\n{str(e)}")
|
||||
|
||||
def open_files_folder(self):
|
||||
"""Open the files folder in the system file manager."""
|
||||
try:
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
subprocess.run(['explorer', str(self.files_dir)])
|
||||
elif platform.system() == 'Darwin': # macOS
|
||||
subprocess.run(['open', str(self.files_dir)])
|
||||
else: # Linux
|
||||
subprocess.run(['xdg-open', str(self.files_dir)])
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to open folder:\n{str(e)}")
|
||||
|
||||
def open_translated_folder(self):
|
||||
"""Open the translated folder in the system file manager."""
|
||||
try:
|
||||
import subprocess
|
||||
import platform
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
subprocess.run(['explorer', str(self.translated_dir)])
|
||||
elif platform.system() == 'Darwin': # macOS
|
||||
subprocess.run(['open', str(self.translated_dir)])
|
||||
else: # Linux
|
||||
subprocess.run(['xdg-open', str(self.translated_dir)])
|
||||
|
||||
except Exception as e:
|
||||
QMessageBox.warning(self, "Error", f"Failed to open folder:\n{str(e)}")
|
||||
|
||||
def get_input_files(self):
|
||||
"""Get list of input files for processing."""
|
||||
input_files = []
|
||||
for i in range(self.input_tree.topLevelItemCount()):
|
||||
item = self.input_tree.topLevelItem(i)
|
||||
file_path = item.data(0, Qt.UserRole)
|
||||
input_files.append(Path(file_path))
|
||||
return input_files
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""Handle widget close event."""
|
||||
if hasattr(self, 'refresh_timer'):
|
||||
self.refresh_timer.stop()
|
||||
event.accept()
|
||||
15
gui/main.py
15
gui/main.py
|
|
@ -22,7 +22,6 @@ from gui.rpgmaker_tab import RPGMakerTab
|
|||
from gui.other_modules_tab import OtherModulesTab
|
||||
from gui.log_viewer import LogViewer
|
||||
from gui.file_manager import FileManager
|
||||
from gui.file_manager_tab import FileManagerTab
|
||||
from gui.translation_tab import TranslationTab
|
||||
|
||||
class DazedMTLGUI(QMainWindow):
|
||||
|
|
@ -120,11 +119,7 @@ class DazedMTLGUI(QMainWindow):
|
|||
self.config_tab.config_changed.connect(self.on_config_changed)
|
||||
self.tab_widget.addTab(self.config_tab, "Configuration")
|
||||
|
||||
# File Manager Tab (New)
|
||||
self.file_manager_tab = FileManagerTab()
|
||||
self.tab_widget.addTab(self.file_manager_tab, "File Manager")
|
||||
|
||||
# Translation Execution Tab
|
||||
# Translation Execution Tab (includes file management)
|
||||
self.translation_tab = TranslationTab(self)
|
||||
self.tab_widget.addTab(self.translation_tab, "Translation")
|
||||
|
||||
|
|
@ -336,14 +331,6 @@ class DazedMTLGUI(QMainWindow):
|
|||
def set_progress(self, value):
|
||||
"""Set the progress bar value (0-100)."""
|
||||
self.progress_bar.setValue(value)
|
||||
|
||||
def get_input_files(self):
|
||||
"""Get list of input files from the file manager."""
|
||||
try:
|
||||
return self.file_manager_tab.get_input_files()
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not get input files: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue