supervertaler 1.9.153__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of supervertaler might be problematic. Click here for more details.
- Supervertaler.py +47886 -0
- modules/__init__.py +10 -0
- modules/ai_actions.py +964 -0
- modules/ai_attachment_manager.py +343 -0
- modules/ai_file_viewer_dialog.py +210 -0
- modules/autofingers_engine.py +466 -0
- modules/cafetran_docx_handler.py +379 -0
- modules/config_manager.py +469 -0
- modules/database_manager.py +1878 -0
- modules/database_migrations.py +417 -0
- modules/dejavurtf_handler.py +779 -0
- modules/document_analyzer.py +427 -0
- modules/docx_handler.py +689 -0
- modules/encoding_repair.py +319 -0
- modules/encoding_repair_Qt.py +393 -0
- modules/encoding_repair_ui.py +481 -0
- modules/feature_manager.py +350 -0
- modules/figure_context_manager.py +340 -0
- modules/file_dialog_helper.py +148 -0
- modules/find_replace.py +164 -0
- modules/find_replace_qt.py +457 -0
- modules/glossary_manager.py +433 -0
- modules/image_extractor.py +188 -0
- modules/keyboard_shortcuts_widget.py +571 -0
- modules/llm_clients.py +1211 -0
- modules/llm_leaderboard.py +737 -0
- modules/llm_superbench_ui.py +1401 -0
- modules/local_llm_setup.py +1104 -0
- modules/model_update_dialog.py +381 -0
- modules/model_version_checker.py +373 -0
- modules/mqxliff_handler.py +638 -0
- modules/non_translatables_manager.py +743 -0
- modules/pdf_rescue_Qt.py +1822 -0
- modules/pdf_rescue_tkinter.py +909 -0
- modules/phrase_docx_handler.py +516 -0
- modules/project_home_panel.py +209 -0
- modules/prompt_assistant.py +357 -0
- modules/prompt_library.py +689 -0
- modules/prompt_library_migration.py +447 -0
- modules/quick_access_sidebar.py +282 -0
- modules/ribbon_widget.py +597 -0
- modules/sdlppx_handler.py +874 -0
- modules/setup_wizard.py +353 -0
- modules/shortcut_manager.py +932 -0
- modules/simple_segmenter.py +128 -0
- modules/spellcheck_manager.py +727 -0
- modules/statuses.py +207 -0
- modules/style_guide_manager.py +315 -0
- modules/superbench_ui.py +1319 -0
- modules/superbrowser.py +329 -0
- modules/supercleaner.py +600 -0
- modules/supercleaner_ui.py +444 -0
- modules/superdocs.py +19 -0
- modules/superdocs_viewer_qt.py +382 -0
- modules/superlookup.py +252 -0
- modules/tag_cleaner.py +260 -0
- modules/tag_manager.py +333 -0
- modules/term_extractor.py +270 -0
- modules/termbase_entry_editor.py +842 -0
- modules/termbase_import_export.py +488 -0
- modules/termbase_manager.py +1060 -0
- modules/termview_widget.py +1172 -0
- modules/theme_manager.py +499 -0
- modules/tm_editor_dialog.py +99 -0
- modules/tm_manager_qt.py +1280 -0
- modules/tm_metadata_manager.py +545 -0
- modules/tmx_editor.py +1461 -0
- modules/tmx_editor_qt.py +2784 -0
- modules/tmx_generator.py +284 -0
- modules/tracked_changes.py +900 -0
- modules/trados_docx_handler.py +430 -0
- modules/translation_memory.py +715 -0
- modules/translation_results_panel.py +2134 -0
- modules/translation_services.py +282 -0
- modules/unified_prompt_library.py +659 -0
- modules/unified_prompt_manager_qt.py +3951 -0
- modules/voice_commands.py +920 -0
- modules/voice_dictation.py +477 -0
- modules/voice_dictation_lite.py +249 -0
- supervertaler-1.9.153.dist-info/METADATA +896 -0
- supervertaler-1.9.153.dist-info/RECORD +85 -0
- supervertaler-1.9.153.dist-info/WHEEL +5 -0
- supervertaler-1.9.153.dist-info/entry_points.txt +2 -0
- supervertaler-1.9.153.dist-info/licenses/LICENSE +21 -0
- supervertaler-1.9.153.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Encoding Repair Module - Qt Edition
|
|
3
|
+
Embeddable version of the text encoding repair tool for detecting and fixing mojibake/encoding corruption
|
|
4
|
+
|
|
5
|
+
This module can be embedded in the main Supervertaler Qt application as a tab.
|
|
6
|
+
Can also be run independently as a standalone application.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import sys
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# Fix import path for standalone mode - must be done before any module imports
|
|
14
|
+
_parent_dir = Path(__file__).parent.parent
|
|
15
|
+
if str(_parent_dir) not in sys.path:
|
|
16
|
+
sys.path.insert(0, str(_parent_dir))
|
|
17
|
+
|
|
18
|
+
from PyQt6.QtWidgets import (
|
|
19
|
+
QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QFileDialog,
|
|
20
|
+
QMessageBox, QPlainTextEdit, QGroupBox, QFrame, QApplication
|
|
21
|
+
)
|
|
22
|
+
from PyQt6.QtCore import Qt, QThread, pyqtSignal
|
|
23
|
+
from PyQt6.QtGui import QFont, QTextOption
|
|
24
|
+
|
|
25
|
+
from modules.encoding_repair import EncodingRepair
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class EncodingRepairQt:
|
|
29
|
+
"""
|
|
30
|
+
Encoding Repair feature - detect and fix text encoding corruption (mojibake)
|
|
31
|
+
Can be embedded in any PyQt6 application as a tab or panel
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, parent_app, standalone=False):
|
|
35
|
+
"""
|
|
36
|
+
Initialize Encoding Repair module
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
parent_app: Reference to the main application (optional, for logging)
|
|
40
|
+
standalone: If True, running as standalone app. If False, embedded in Supervertaler
|
|
41
|
+
"""
|
|
42
|
+
self.parent_app = parent_app
|
|
43
|
+
self.standalone = standalone
|
|
44
|
+
|
|
45
|
+
# Initialize logging
|
|
46
|
+
self.log = parent_app.log if hasattr(parent_app, 'log') else print
|
|
47
|
+
|
|
48
|
+
# State
|
|
49
|
+
self.selected_path = None
|
|
50
|
+
self.is_folder = False
|
|
51
|
+
|
|
52
|
+
def log_message(self, message: str):
|
|
53
|
+
"""Log a message to the parent app's log if available"""
|
|
54
|
+
if hasattr(self.parent_app, 'log'):
|
|
55
|
+
self.parent_app.log(f"[Encoding Repair] {message}")
|
|
56
|
+
else:
|
|
57
|
+
print(f"[Encoding Repair] {message}")
|
|
58
|
+
|
|
59
|
+
def create_tab(self, parent: QWidget):
|
|
60
|
+
"""
|
|
61
|
+
Create the Encoding Repair tab UI
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
parent: The QWidget container for the tab
|
|
65
|
+
"""
|
|
66
|
+
# Main layout
|
|
67
|
+
main_layout = QVBoxLayout(parent)
|
|
68
|
+
main_layout.setContentsMargins(10, 10, 10, 10)
|
|
69
|
+
main_layout.setSpacing(5)
|
|
70
|
+
|
|
71
|
+
# ===== HEADER: Standard Template (matches PDF Rescue / TMX Editor style) =====
|
|
72
|
+
header = QLabel("š§ Encoding Repair")
|
|
73
|
+
header.setStyleSheet("font-size: 16pt; font-weight: bold; color: #1976D2;")
|
|
74
|
+
main_layout.addWidget(header, 0) # 0 = no stretch, stays compact
|
|
75
|
+
|
|
76
|
+
# Description box (matches Universal Lookup / PDF Rescue / TMX Editor style)
|
|
77
|
+
description = QLabel(
|
|
78
|
+
"Detect and fix text encoding corruption (mojibake) in translation files.\n"
|
|
79
|
+
"Automatically repairs UTF-8 text incorrectly decoded as Latin-1 or Windows-1252."
|
|
80
|
+
)
|
|
81
|
+
description.setWordWrap(True)
|
|
82
|
+
description.setStyleSheet("color: #666; padding: 5px; background-color: #E3F2FD; border-radius: 3px;")
|
|
83
|
+
main_layout.addWidget(description, 0) # 0 = no stretch, stays compact
|
|
84
|
+
|
|
85
|
+
# ===== FILE SELECTION SECTION =====
|
|
86
|
+
file_group = QGroupBox("š Select File or Folder")
|
|
87
|
+
file_layout = QVBoxLayout(file_group)
|
|
88
|
+
file_layout.setSpacing(10)
|
|
89
|
+
|
|
90
|
+
# Selected path display
|
|
91
|
+
self.path_label = QLabel("No file or folder selected")
|
|
92
|
+
self.path_label.setWordWrap(True)
|
|
93
|
+
self.path_label.setStyleSheet("color: #666; padding: 5px; background-color: #F5F5F5; border-radius: 3px;")
|
|
94
|
+
file_layout.addWidget(self.path_label)
|
|
95
|
+
|
|
96
|
+
# Selection buttons
|
|
97
|
+
select_layout = QHBoxLayout()
|
|
98
|
+
select_layout.setSpacing(10)
|
|
99
|
+
|
|
100
|
+
select_file_btn = QPushButton("š Select File")
|
|
101
|
+
select_file_btn.clicked.connect(self._select_file)
|
|
102
|
+
select_file_btn.setStyleSheet("background-color: #2196F3; color: white; font-weight: bold; padding: 6px 12px;")
|
|
103
|
+
select_layout.addWidget(select_file_btn)
|
|
104
|
+
|
|
105
|
+
select_folder_btn = QPushButton("š Select Folder")
|
|
106
|
+
select_folder_btn.clicked.connect(self._select_folder)
|
|
107
|
+
select_folder_btn.setStyleSheet("background-color: #9C27B0; color: white; font-weight: bold; padding: 6px 12px;")
|
|
108
|
+
select_layout.addWidget(select_folder_btn)
|
|
109
|
+
|
|
110
|
+
select_layout.addStretch()
|
|
111
|
+
file_layout.addLayout(select_layout)
|
|
112
|
+
|
|
113
|
+
main_layout.addWidget(file_group, 0)
|
|
114
|
+
|
|
115
|
+
# ===== ACTIONS SECTION =====
|
|
116
|
+
action_group = QGroupBox("š Detect & Repair")
|
|
117
|
+
action_layout = QVBoxLayout(action_group)
|
|
118
|
+
action_layout.setSpacing(10)
|
|
119
|
+
|
|
120
|
+
# Action buttons
|
|
121
|
+
action_btn_layout = QHBoxLayout()
|
|
122
|
+
action_btn_layout.setSpacing(10)
|
|
123
|
+
|
|
124
|
+
scan_btn = QPushButton("š Scan for Corruption")
|
|
125
|
+
scan_btn.clicked.connect(self._scan_files)
|
|
126
|
+
scan_btn.setStyleSheet("background-color: #FF9800; color: white; font-weight: bold; padding: 6px 12px;")
|
|
127
|
+
action_btn_layout.addWidget(scan_btn)
|
|
128
|
+
|
|
129
|
+
repair_btn = QPushButton("ā
Repair Files")
|
|
130
|
+
repair_btn.clicked.connect(self._repair_files)
|
|
131
|
+
repair_btn.setStyleSheet("background-color: #4CAF50; color: white; font-weight: bold; padding: 6px 12px;")
|
|
132
|
+
action_btn_layout.addWidget(repair_btn)
|
|
133
|
+
|
|
134
|
+
clear_btn = QPushButton("ā Clear")
|
|
135
|
+
clear_btn.clicked.connect(self._clear_results)
|
|
136
|
+
clear_btn.setStyleSheet("background-color: #9E9E9E; color: white; padding: 6px 12px;")
|
|
137
|
+
action_btn_layout.addWidget(clear_btn)
|
|
138
|
+
|
|
139
|
+
action_btn_layout.addStretch()
|
|
140
|
+
action_layout.addLayout(action_btn_layout)
|
|
141
|
+
|
|
142
|
+
main_layout.addWidget(action_group, 0)
|
|
143
|
+
|
|
144
|
+
# ===== RESULTS SECTION =====
|
|
145
|
+
results_group = QGroupBox("š Results")
|
|
146
|
+
results_layout = QVBoxLayout(results_group)
|
|
147
|
+
results_layout.setContentsMargins(5, 5, 5, 5)
|
|
148
|
+
|
|
149
|
+
self.results_text = QPlainTextEdit()
|
|
150
|
+
self.results_text.setReadOnly(True)
|
|
151
|
+
self.results_text.setFont(QFont("Consolas", 9))
|
|
152
|
+
self.results_text.setStyleSheet("""
|
|
153
|
+
QPlainTextEdit {
|
|
154
|
+
background-color: #F5F5F5;
|
|
155
|
+
border: 1px solid #DDD;
|
|
156
|
+
border-radius: 3px;
|
|
157
|
+
}
|
|
158
|
+
""")
|
|
159
|
+
results_layout.addWidget(self.results_text, 1) # 1 = stretch factor
|
|
160
|
+
|
|
161
|
+
main_layout.addWidget(results_group, 1) # 1 = stretch factor, expands to fill space
|
|
162
|
+
|
|
163
|
+
def _select_file(self):
|
|
164
|
+
"""Select a single file for encoding repair"""
|
|
165
|
+
file_path, _ = QFileDialog.getOpenFileName(
|
|
166
|
+
None, "Select file to scan",
|
|
167
|
+
"", "Text files (*.txt);;All files (*.*)"
|
|
168
|
+
)
|
|
169
|
+
if file_path:
|
|
170
|
+
self.selected_path = file_path
|
|
171
|
+
self.is_folder = False
|
|
172
|
+
self.path_label.setText(f"File: {file_path}")
|
|
173
|
+
self.log_message(f"Selected file: {file_path}")
|
|
174
|
+
|
|
175
|
+
def _select_folder(self):
|
|
176
|
+
"""Select a folder for encoding repair"""
|
|
177
|
+
folder_path = QFileDialog.getExistingDirectory(
|
|
178
|
+
None, "Select folder to scan"
|
|
179
|
+
)
|
|
180
|
+
if folder_path:
|
|
181
|
+
self.selected_path = folder_path
|
|
182
|
+
self.is_folder = True
|
|
183
|
+
self.path_label.setText(f"Folder: {folder_path}")
|
|
184
|
+
self.log_message(f"Selected folder: {folder_path}")
|
|
185
|
+
|
|
186
|
+
def _scan_files(self):
|
|
187
|
+
"""Scan selected file(s) for encoding corruption"""
|
|
188
|
+
if not self.selected_path:
|
|
189
|
+
QMessageBox.warning(None, "No Selection", "Please select a file or folder first.")
|
|
190
|
+
return
|
|
191
|
+
|
|
192
|
+
# Clear results
|
|
193
|
+
self.results_text.clear()
|
|
194
|
+
self.results_text.appendPlainText("Scanning for encoding corruption...\n")
|
|
195
|
+
QApplication.processEvents()
|
|
196
|
+
|
|
197
|
+
try:
|
|
198
|
+
if self.is_folder:
|
|
199
|
+
# Scan all text files in folder
|
|
200
|
+
folder = Path(self.selected_path)
|
|
201
|
+
text_files = list(folder.rglob('*.txt'))
|
|
202
|
+
|
|
203
|
+
if not text_files:
|
|
204
|
+
self.results_text.appendPlainText("ā ļø No text files found in folder\n")
|
|
205
|
+
return
|
|
206
|
+
|
|
207
|
+
self.results_text.appendPlainText(f"Scanning {len(text_files)} file(s)...\n\n")
|
|
208
|
+
QApplication.processEvents()
|
|
209
|
+
|
|
210
|
+
total_corruptions = 0
|
|
211
|
+
files_with_corruption = 0
|
|
212
|
+
|
|
213
|
+
for filepath in text_files:
|
|
214
|
+
try:
|
|
215
|
+
with open(filepath, 'r', encoding='utf-8') as f:
|
|
216
|
+
content = f.read()
|
|
217
|
+
|
|
218
|
+
has_corruption, corruption_count, patterns = EncodingRepair.detect_corruption(content)
|
|
219
|
+
|
|
220
|
+
if has_corruption:
|
|
221
|
+
files_with_corruption += 1
|
|
222
|
+
total_corruptions += corruption_count
|
|
223
|
+
|
|
224
|
+
self.results_text.appendPlainText(f"š {filepath.name}\n")
|
|
225
|
+
self.results_text.appendPlainText(f" ā Found {corruption_count} corruption(s)\n")
|
|
226
|
+
for pattern in patterns:
|
|
227
|
+
self.results_text.appendPlainText(f" ⢠{pattern}\n")
|
|
228
|
+
self.results_text.appendPlainText("\n")
|
|
229
|
+
except Exception as e:
|
|
230
|
+
self.results_text.appendPlainText(f"ā Error reading {filepath.name}: {str(e)}\n")
|
|
231
|
+
|
|
232
|
+
QApplication.processEvents()
|
|
233
|
+
|
|
234
|
+
self.results_text.appendPlainText("\n--- Summary ---\n")
|
|
235
|
+
self.results_text.appendPlainText(f"Files with corruption: {files_with_corruption}\n")
|
|
236
|
+
self.results_text.appendPlainText(f"Total corruptions found: {total_corruptions}\n")
|
|
237
|
+
|
|
238
|
+
else:
|
|
239
|
+
# Scan single file
|
|
240
|
+
try:
|
|
241
|
+
with open(self.selected_path, 'r', encoding='utf-8') as f:
|
|
242
|
+
content = f.read()
|
|
243
|
+
|
|
244
|
+
has_corruption, corruption_count, patterns = EncodingRepair.detect_corruption(content)
|
|
245
|
+
|
|
246
|
+
filename = Path(self.selected_path).name
|
|
247
|
+
|
|
248
|
+
if has_corruption:
|
|
249
|
+
self.results_text.appendPlainText(f"š {filename}\n")
|
|
250
|
+
self.results_text.appendPlainText("ā Encoding corruption detected!\n\n")
|
|
251
|
+
self.results_text.appendPlainText(f"Found {corruption_count} corruption pattern(s):\n\n")
|
|
252
|
+
for pattern in patterns:
|
|
253
|
+
self.results_text.appendPlainText(f" ⢠{pattern}\n")
|
|
254
|
+
else:
|
|
255
|
+
self.results_text.appendPlainText(f"š {filename}\n")
|
|
256
|
+
self.results_text.appendPlainText("ā No encoding corruption found\n")
|
|
257
|
+
|
|
258
|
+
except Exception as e:
|
|
259
|
+
self.results_text.appendPlainText(f"ā Error: {str(e)}\n")
|
|
260
|
+
|
|
261
|
+
self.log_message("Scan completed")
|
|
262
|
+
|
|
263
|
+
except Exception as e:
|
|
264
|
+
QMessageBox.critical(None, "Error", f"Failed to scan files:\n\n{str(e)}")
|
|
265
|
+
self.log_message(f"Scan error: {str(e)}")
|
|
266
|
+
|
|
267
|
+
def _repair_files(self):
|
|
268
|
+
"""Fix encoding corruption in selected file(s)"""
|
|
269
|
+
if not self.selected_path:
|
|
270
|
+
QMessageBox.warning(None, "No Selection", "Please select a file or folder first.")
|
|
271
|
+
return
|
|
272
|
+
|
|
273
|
+
# Confirm before repair
|
|
274
|
+
if self.is_folder:
|
|
275
|
+
msg = f"Repair all text files in folder?\n\n{self.selected_path}\n\nA backup will be created for each file."
|
|
276
|
+
else:
|
|
277
|
+
msg = f"Repair file?\n\n{Path(self.selected_path).name}\n\nA backup will be created."
|
|
278
|
+
|
|
279
|
+
reply = QMessageBox.question(
|
|
280
|
+
None, "Confirm Repair", msg,
|
|
281
|
+
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
if reply != QMessageBox.StandardButton.Yes:
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
# Append to results
|
|
288
|
+
self.results_text.appendPlainText("\n--- Repair Process ---\n")
|
|
289
|
+
QApplication.processEvents()
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
if self.is_folder:
|
|
293
|
+
# Repair all text files in folder
|
|
294
|
+
folder = Path(self.selected_path)
|
|
295
|
+
text_files = list(folder.rglob('*.txt'))
|
|
296
|
+
|
|
297
|
+
if not text_files:
|
|
298
|
+
self.results_text.appendPlainText("ā ļø No text files found\n")
|
|
299
|
+
return
|
|
300
|
+
|
|
301
|
+
repaired_count = 0
|
|
302
|
+
for filepath in text_files:
|
|
303
|
+
try:
|
|
304
|
+
# Create backup
|
|
305
|
+
backup_path = f"{filepath}.backup"
|
|
306
|
+
with open(filepath, 'rb') as f_src:
|
|
307
|
+
with open(backup_path, 'wb') as f_dst:
|
|
308
|
+
f_dst.write(f_src.read())
|
|
309
|
+
|
|
310
|
+
# Repair
|
|
311
|
+
success, message, stats = EncodingRepair.repair_file(str(filepath))
|
|
312
|
+
|
|
313
|
+
if success:
|
|
314
|
+
if stats.get('has_corruption', False):
|
|
315
|
+
repaired_count += 1
|
|
316
|
+
self.results_text.appendPlainText(f"ā
{filepath.name}\n")
|
|
317
|
+
self.results_text.appendPlainText(f" Fixed {stats.get('corruption_count', 0)} corruption(s)\n")
|
|
318
|
+
else:
|
|
319
|
+
self.results_text.appendPlainText(f"ā¹ļø {filepath.name} (no corruption found)\n")
|
|
320
|
+
else:
|
|
321
|
+
self.results_text.appendPlainText(f"ā {filepath.name}: {message}\n")
|
|
322
|
+
|
|
323
|
+
QApplication.processEvents()
|
|
324
|
+
|
|
325
|
+
except Exception as e:
|
|
326
|
+
self.results_text.appendPlainText(f"ā Error repairing {filepath.name}: {str(e)}\n")
|
|
327
|
+
|
|
328
|
+
self.results_text.appendPlainText(f"\nā
Repaired {repaired_count}/{len(text_files)} file(s)\n")
|
|
329
|
+
QMessageBox.information(None, "Repair Complete", f"Repaired {repaired_count} file(s) in folder.")
|
|
330
|
+
|
|
331
|
+
else:
|
|
332
|
+
# Repair single file
|
|
333
|
+
# Create backup
|
|
334
|
+
backup_path = f"{self.selected_path}.backup"
|
|
335
|
+
with open(self.selected_path, 'rb') as f_src:
|
|
336
|
+
with open(backup_path, 'wb') as f_dst:
|
|
337
|
+
f_dst.write(f_src.read())
|
|
338
|
+
|
|
339
|
+
# Repair
|
|
340
|
+
success, message, stats = EncodingRepair.repair_file(self.selected_path)
|
|
341
|
+
|
|
342
|
+
if success:
|
|
343
|
+
self.results_text.appendPlainText(message + "\n")
|
|
344
|
+
if 'corruption_count' in stats and stats['corruption_count'] > 0:
|
|
345
|
+
self.results_text.appendPlainText(f"File size: {stats.get('original_size', 0)} ā {stats.get('repaired_size', 0)} bytes\n")
|
|
346
|
+
self.results_text.appendPlainText(f"Backup created: {backup_path}\n")
|
|
347
|
+
QMessageBox.information(None, "Success", f"File repaired successfully!\n\nBackup saved as: {backup_path}")
|
|
348
|
+
else:
|
|
349
|
+
self.results_text.appendPlainText(message + "\n")
|
|
350
|
+
QMessageBox.critical(None, "Error", f"Repair failed:\n\n{message}")
|
|
351
|
+
|
|
352
|
+
self.log_message("Repair completed")
|
|
353
|
+
|
|
354
|
+
except Exception as e:
|
|
355
|
+
QMessageBox.critical(None, "Error", f"Failed to repair files:\n\n{str(e)}")
|
|
356
|
+
self.log_message(f"Repair error: {str(e)}")
|
|
357
|
+
|
|
358
|
+
def _clear_results(self):
|
|
359
|
+
"""Clear the results display"""
|
|
360
|
+
self.results_text.clear()
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# === Standalone Application ===
|
|
364
|
+
|
|
365
|
+
if __name__ == "__main__":
|
|
366
|
+
"""Run Encoding Repair as a standalone application"""
|
|
367
|
+
from PyQt6.QtWidgets import QMainWindow
|
|
368
|
+
|
|
369
|
+
class StandaloneApp(QMainWindow):
|
|
370
|
+
"""Minimal parent app for standalone mode"""
|
|
371
|
+
def __init__(self):
|
|
372
|
+
super().__init__()
|
|
373
|
+
self.setWindowTitle("Encoding Repair Tool - Text Encoding Corruption Fixer")
|
|
374
|
+
self.setGeometry(100, 100, 900, 700)
|
|
375
|
+
|
|
376
|
+
# Create central widget
|
|
377
|
+
central_widget = QWidget()
|
|
378
|
+
self.setCentralWidget(central_widget)
|
|
379
|
+
|
|
380
|
+
# Create Encoding Repair widget
|
|
381
|
+
self.encoding_repair = EncodingRepairQt(self, standalone=True)
|
|
382
|
+
self.encoding_repair.create_tab(central_widget)
|
|
383
|
+
|
|
384
|
+
def log(self, message: str):
|
|
385
|
+
"""Simple log method for standalone mode"""
|
|
386
|
+
print(message)
|
|
387
|
+
|
|
388
|
+
# Create and run application
|
|
389
|
+
app = QApplication(sys.argv)
|
|
390
|
+
window = StandaloneApp()
|
|
391
|
+
window.show()
|
|
392
|
+
sys.exit(app.exec())
|
|
393
|
+
|