supervertaler 1.9.163__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.
Files changed (85) hide show
  1. Supervertaler.py +48473 -0
  2. modules/__init__.py +10 -0
  3. modules/ai_actions.py +964 -0
  4. modules/ai_attachment_manager.py +343 -0
  5. modules/ai_file_viewer_dialog.py +210 -0
  6. modules/autofingers_engine.py +466 -0
  7. modules/cafetran_docx_handler.py +379 -0
  8. modules/config_manager.py +469 -0
  9. modules/database_manager.py +1911 -0
  10. modules/database_migrations.py +417 -0
  11. modules/dejavurtf_handler.py +779 -0
  12. modules/document_analyzer.py +427 -0
  13. modules/docx_handler.py +689 -0
  14. modules/encoding_repair.py +319 -0
  15. modules/encoding_repair_Qt.py +393 -0
  16. modules/encoding_repair_ui.py +481 -0
  17. modules/feature_manager.py +350 -0
  18. modules/figure_context_manager.py +340 -0
  19. modules/file_dialog_helper.py +148 -0
  20. modules/find_replace.py +164 -0
  21. modules/find_replace_qt.py +457 -0
  22. modules/glossary_manager.py +433 -0
  23. modules/image_extractor.py +188 -0
  24. modules/keyboard_shortcuts_widget.py +571 -0
  25. modules/llm_clients.py +1211 -0
  26. modules/llm_leaderboard.py +737 -0
  27. modules/llm_superbench_ui.py +1401 -0
  28. modules/local_llm_setup.py +1104 -0
  29. modules/model_update_dialog.py +381 -0
  30. modules/model_version_checker.py +373 -0
  31. modules/mqxliff_handler.py +638 -0
  32. modules/non_translatables_manager.py +743 -0
  33. modules/pdf_rescue_Qt.py +1822 -0
  34. modules/pdf_rescue_tkinter.py +909 -0
  35. modules/phrase_docx_handler.py +516 -0
  36. modules/project_home_panel.py +209 -0
  37. modules/prompt_assistant.py +357 -0
  38. modules/prompt_library.py +689 -0
  39. modules/prompt_library_migration.py +447 -0
  40. modules/quick_access_sidebar.py +282 -0
  41. modules/ribbon_widget.py +597 -0
  42. modules/sdlppx_handler.py +874 -0
  43. modules/setup_wizard.py +353 -0
  44. modules/shortcut_manager.py +932 -0
  45. modules/simple_segmenter.py +128 -0
  46. modules/spellcheck_manager.py +727 -0
  47. modules/statuses.py +207 -0
  48. modules/style_guide_manager.py +315 -0
  49. modules/superbench_ui.py +1319 -0
  50. modules/superbrowser.py +329 -0
  51. modules/supercleaner.py +600 -0
  52. modules/supercleaner_ui.py +444 -0
  53. modules/superdocs.py +19 -0
  54. modules/superdocs_viewer_qt.py +382 -0
  55. modules/superlookup.py +252 -0
  56. modules/tag_cleaner.py +260 -0
  57. modules/tag_manager.py +351 -0
  58. modules/term_extractor.py +270 -0
  59. modules/termbase_entry_editor.py +842 -0
  60. modules/termbase_import_export.py +488 -0
  61. modules/termbase_manager.py +1060 -0
  62. modules/termview_widget.py +1176 -0
  63. modules/theme_manager.py +499 -0
  64. modules/tm_editor_dialog.py +99 -0
  65. modules/tm_manager_qt.py +1280 -0
  66. modules/tm_metadata_manager.py +545 -0
  67. modules/tmx_editor.py +1461 -0
  68. modules/tmx_editor_qt.py +2784 -0
  69. modules/tmx_generator.py +284 -0
  70. modules/tracked_changes.py +900 -0
  71. modules/trados_docx_handler.py +430 -0
  72. modules/translation_memory.py +715 -0
  73. modules/translation_results_panel.py +2134 -0
  74. modules/translation_services.py +282 -0
  75. modules/unified_prompt_library.py +659 -0
  76. modules/unified_prompt_manager_qt.py +3951 -0
  77. modules/voice_commands.py +920 -0
  78. modules/voice_dictation.py +477 -0
  79. modules/voice_dictation_lite.py +249 -0
  80. supervertaler-1.9.163.dist-info/METADATA +906 -0
  81. supervertaler-1.9.163.dist-info/RECORD +85 -0
  82. supervertaler-1.9.163.dist-info/WHEEL +5 -0
  83. supervertaler-1.9.163.dist-info/entry_points.txt +2 -0
  84. supervertaler-1.9.163.dist-info/licenses/LICENSE +21 -0
  85. supervertaler-1.9.163.dist-info/top_level.txt +2 -0
@@ -0,0 +1,329 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ =============================================================================
4
+ MODULE: Superbrowser - Multi-Chat AI Browser
5
+ =============================================================================
6
+ Display multiple AI chat pages side by side in a single interface.
7
+ Supports ChatGPT, Claude, and Gemini in a three-column resizable layout.
8
+
9
+ Author: Michael Beijer
10
+ Date: November 18, 2025
11
+ Version: 1.0.0
12
+ =============================================================================
13
+ """
14
+
15
+ import os
16
+ import shutil
17
+ from PyQt6.QtCore import QUrl, Qt
18
+ from PyQt6.QtWidgets import (
19
+ QWidget, QHBoxLayout, QVBoxLayout, QLabel,
20
+ QSplitter, QPushButton, QLineEdit, QComboBox,
21
+ QGroupBox, QFormLayout
22
+ )
23
+ from PyQt6.QtWebEngineWidgets import QWebEngineView
24
+ from PyQt6.QtWebEngineCore import QWebEngineProfile
25
+ from PyQt6.QtGui import QPalette, QColor
26
+
27
+
28
+ def _clear_corrupted_cache(storage_path: str):
29
+ """
30
+ Clear potentially corrupted Chromium cache folders.
31
+ These can cause 'wrong file structure on disk' errors on startup.
32
+ """
33
+ problematic_dirs = [
34
+ os.path.join(storage_path, "Shared Dictionary"),
35
+ os.path.join(storage_path, "cache", "Shared Dictionary"),
36
+ ]
37
+ for dir_path in problematic_dirs:
38
+ if os.path.exists(dir_path):
39
+ try:
40
+ shutil.rmtree(dir_path)
41
+ except Exception:
42
+ pass # Silently ignore - may be in use
43
+
44
+
45
+ class ChatColumn(QWidget):
46
+ """A column containing a chat interface with web browser"""
47
+
48
+ def __init__(self, title, url, header_color, parent=None, user_data_path=None):
49
+ super().__init__(parent)
50
+ self.title = title
51
+ self.url = url
52
+ self.header_color = header_color
53
+ self.user_data_path = user_data_path # Store user data path
54
+ self.init_ui()
55
+
56
+ def init_ui(self):
57
+ """Initialize the chat column UI"""
58
+ layout = QVBoxLayout()
59
+ layout.setContentsMargins(0, 0, 0, 0)
60
+ layout.setSpacing(0)
61
+
62
+ # Tiny header label with provider name
63
+ header = QLabel(self.title)
64
+ header.setAlignment(Qt.AlignmentFlag.AlignCenter)
65
+ header.setStyleSheet(f"""
66
+ QLabel {{
67
+ background-color: {self.header_color};
68
+ color: white;
69
+ padding: 0px;
70
+ margin: 0px;
71
+ font-weight: bold;
72
+ font-size: 9px;
73
+ max-height: 20px;
74
+ min-height: 20px;
75
+ }}
76
+ """)
77
+
78
+ # URL bar for navigation
79
+ url_layout = QHBoxLayout()
80
+ url_layout.setContentsMargins(1, 1, 1, 1)
81
+
82
+ self.url_input = QLineEdit()
83
+ self.url_input.setText(self.url)
84
+ self.url_input.setPlaceholderText("Enter URL...")
85
+ self.url_input.returnPressed.connect(self.load_url)
86
+
87
+ reload_btn = QPushButton("↻")
88
+ reload_btn.setMaximumWidth(40)
89
+ reload_btn.setToolTip("Reload page")
90
+ reload_btn.clicked.connect(self.reload_page)
91
+
92
+ home_btn = QPushButton("⌂")
93
+ home_btn.setMaximumWidth(40)
94
+ home_btn.setToolTip("Go to home URL")
95
+ home_btn.clicked.connect(self.go_home)
96
+
97
+ url_layout.addWidget(self.url_input)
98
+ url_layout.addWidget(reload_btn)
99
+ url_layout.addWidget(home_btn)
100
+
101
+ # Web view with persistent profile
102
+ # Create or use persistent profile to save cookies and session data
103
+ profile_name = f"superbrowser_{self.title.lower()}"
104
+ self.profile = QWebEngineProfile(profile_name, self)
105
+
106
+ # Set persistent storage path using user_data_path from parent
107
+ if self.user_data_path:
108
+ storage_path = os.path.join(str(self.user_data_path), "superbrowser_profiles", profile_name)
109
+ else:
110
+ # Fallback to script directory if user_data_path not provided
111
+ dev_mode_marker = os.path.join(os.path.dirname(__file__), "..", ".supervertaler.local")
112
+ base_folder = "user_data_private" if os.path.exists(dev_mode_marker) else "user_data"
113
+ storage_path = os.path.join(os.path.dirname(__file__), "..", base_folder, "superbrowser_profiles", profile_name)
114
+ os.makedirs(storage_path, exist_ok=True)
115
+
116
+ # Clear potentially corrupted cache to prevent Chromium errors
117
+ _clear_corrupted_cache(storage_path)
118
+
119
+ self.profile.setPersistentStoragePath(storage_path)
120
+ self.profile.setCachePath(os.path.join(storage_path, "cache"))
121
+
122
+ # Enable persistent cookies
123
+ self.profile.setPersistentCookiesPolicy(QWebEngineProfile.PersistentCookiesPolicy.AllowPersistentCookies)
124
+
125
+ # Create web view with this profile
126
+ from PyQt6.QtWebEngineWidgets import QWebEngineView
127
+ from PyQt6.QtWebEngineCore import QWebEnginePage
128
+
129
+ page = QWebEnginePage(self.profile, self)
130
+ self.web_view = QWebEngineView()
131
+ self.web_view.setPage(page)
132
+ self.web_view.setUrl(QUrl(self.url))
133
+
134
+ # Update URL bar when page changes
135
+ self.web_view.urlChanged.connect(self.update_url_bar)
136
+
137
+ # Add to layout (tiny header, URL bar, then browser)
138
+ layout.addWidget(header)
139
+ layout.addLayout(url_layout)
140
+ layout.addWidget(self.web_view)
141
+
142
+ self.setLayout(layout)
143
+
144
+ def load_url(self):
145
+ """Load URL from input field"""
146
+ url_text = self.url_input.text().strip()
147
+ if not url_text.startswith(('http://', 'https://')):
148
+ url_text = 'https://' + url_text
149
+ self.web_view.setUrl(QUrl(url_text))
150
+
151
+ def reload_page(self):
152
+ """Reload the current page"""
153
+ self.web_view.reload()
154
+
155
+ def go_home(self):
156
+ """Go back to the home URL"""
157
+ self.web_view.setUrl(QUrl(self.url))
158
+
159
+ def update_url_bar(self, url):
160
+ """Update URL bar when page changes"""
161
+ self.url_input.setText(url.toString())
162
+
163
+
164
+ class SuperbrowserWidget(QWidget):
165
+ """
166
+ Superbrowser - Multi-Chat AI Browser Widget
167
+
168
+ Displays multiple AI chat interfaces side by side for easy comparison
169
+ and concurrent interaction with different AI models.
170
+ """
171
+
172
+ def __init__(self, parent=None, user_data_path=None):
173
+ super().__init__(parent)
174
+ self.parent_window = parent
175
+ self.user_data_path = user_data_path # Store user data path for profiles
176
+
177
+ # Default URLs for AI chat interfaces
178
+ self.chatgpt_url = "https://chatgpt.com/"
179
+ self.claude_url = "https://claude.ai/"
180
+ self.gemini_url = "https://gemini.google.com/"
181
+
182
+ self.init_ui()
183
+
184
+ def init_ui(self):
185
+ """Initialize the Superbrowser UI"""
186
+ main_layout = QVBoxLayout()
187
+ main_layout.setContentsMargins(5, 5, 5, 5)
188
+ main_layout.setSpacing(5)
189
+
190
+ # Compact title bar with toggle button
191
+ title_bar_layout = QHBoxLayout()
192
+ title_bar_layout.setContentsMargins(0, 0, 0, 0)
193
+
194
+ title_label = QLabel("🌐 Superbrowser - Multi-Chat AI Browser")
195
+ title_label.setStyleSheet("""
196
+ QLabel {
197
+ font-size: 12px;
198
+ font-weight: bold;
199
+ color: #2c3e50;
200
+ padding: 3px;
201
+ }
202
+ """)
203
+
204
+ description = QLabel(
205
+ "View and interact with ChatGPT, Claude, and Gemini side by side. "
206
+ "Perfect for comparing responses or maintaining multiple conversation threads."
207
+ )
208
+ description.setWordWrap(True)
209
+ description.setStyleSheet("color: #7f8c8d; padding: 3px; font-size: 10px;")
210
+
211
+ # Toggle button for configuration section
212
+ self.toggle_config_btn = QPushButton("▼ Hide Configuration")
213
+ self.toggle_config_btn.setMaximumWidth(150)
214
+ self.toggle_config_btn.setStyleSheet("""
215
+ QPushButton {
216
+ background-color: #3498db;
217
+ color: white;
218
+ border: none;
219
+ padding: 4px 8px;
220
+ font-size: 10px;
221
+ border-radius: 3px;
222
+ }
223
+ QPushButton:hover {
224
+ background-color: #2980b9;
225
+ }
226
+ """)
227
+ self.toggle_config_btn.clicked.connect(self.toggle_configuration)
228
+
229
+ title_bar_layout.addWidget(title_label)
230
+ title_bar_layout.addWidget(description, stretch=1)
231
+ title_bar_layout.addWidget(self.toggle_config_btn)
232
+
233
+ main_layout.addLayout(title_bar_layout)
234
+
235
+ # URL Configuration section (collapsible)
236
+ self.config_group = QGroupBox("🔧 Configuration")
237
+ self.config_group.setStyleSheet("QGroupBox { font-size: 10px; font-weight: bold; }")
238
+ config_layout = QFormLayout()
239
+
240
+ self.chatgpt_url_input = QLineEdit(self.chatgpt_url)
241
+ self.chatgpt_url_input.setStyleSheet("font-size: 10px;")
242
+ self.claude_url_input = QLineEdit(self.claude_url)
243
+ self.claude_url_input.setStyleSheet("font-size: 10px;")
244
+ self.gemini_url_input = QLineEdit(self.gemini_url)
245
+ self.gemini_url_input.setStyleSheet("font-size: 10px;")
246
+
247
+ config_layout.addRow("ChatGPT URL:", self.chatgpt_url_input)
248
+ config_layout.addRow("Claude URL:", self.claude_url_input)
249
+ config_layout.addRow("Gemini URL:", self.gemini_url_input)
250
+
251
+ update_btn = QPushButton("Update URLs")
252
+ update_btn.setStyleSheet("font-size: 10px; padding: 3px;")
253
+ update_btn.clicked.connect(self.update_urls)
254
+ config_layout.addRow("", update_btn)
255
+
256
+ self.config_group.setLayout(config_layout)
257
+ self.config_group.setMaximumHeight(150)
258
+ main_layout.addWidget(self.config_group)
259
+
260
+ # Splitter for resizable columns
261
+ splitter = QSplitter(Qt.Orientation.Horizontal)
262
+ splitter.setHandleWidth(3)
263
+
264
+ # Create chat columns - pass user_data_path for profile storage
265
+ self.chatgpt_column = ChatColumn("ChatGPT", self.chatgpt_url, "#10a37f", self, user_data_path=self.user_data_path)
266
+ self.claude_column = ChatColumn("Claude", self.claude_url, "#c17c4f", self, user_data_path=self.user_data_path)
267
+ self.gemini_column = ChatColumn("Gemini", self.gemini_url, "#4285f4", self, user_data_path=self.user_data_path)
268
+
269
+ # Add columns to splitter
270
+ splitter.addWidget(self.chatgpt_column)
271
+ splitter.addWidget(self.claude_column)
272
+ splitter.addWidget(self.gemini_column)
273
+
274
+ # Set equal sizes for all columns
275
+ splitter.setSizes([600, 600, 600])
276
+
277
+ # Add splitter to main layout (takes most of the space)
278
+ main_layout.addWidget(splitter, stretch=1)
279
+
280
+ self.setLayout(main_layout)
281
+
282
+ def toggle_configuration(self):
283
+ """Toggle visibility of configuration section"""
284
+ if self.config_group.isVisible():
285
+ self.config_group.setVisible(False)
286
+ self.toggle_config_btn.setText("▶ Show Configuration")
287
+ else:
288
+ self.config_group.setVisible(True)
289
+ self.toggle_config_btn.setText("▼ Hide Configuration")
290
+
291
+ def update_urls(self):
292
+ """Update the URLs for all chat columns"""
293
+ self.chatgpt_url = self.chatgpt_url_input.text().strip() or self.chatgpt_url
294
+ self.claude_url = self.claude_url_input.text().strip() or self.claude_url
295
+ self.gemini_url = self.gemini_url_input.text().strip() or self.gemini_url
296
+
297
+ # Update the columns
298
+ self.chatgpt_column.url = self.chatgpt_url
299
+ self.claude_column.url = self.claude_url
300
+ self.gemini_column.url = self.gemini_url
301
+
302
+ # Reload to new URLs
303
+ self.chatgpt_column.go_home()
304
+ self.claude_column.go_home()
305
+ self.gemini_column.go_home()
306
+
307
+
308
+ # ============================================================================
309
+ # STANDALONE USAGE
310
+ # ============================================================================
311
+
312
+ if __name__ == "__main__":
313
+ import sys
314
+ from PyQt6.QtWidgets import QApplication, QMainWindow
315
+
316
+ app = QApplication(sys.argv)
317
+ app.setApplicationName("Superbrowser")
318
+
319
+ # Create main window for testing
320
+ window = QMainWindow()
321
+ window.setWindowTitle("Superbrowser - Multi-Chat AI Browser")
322
+ window.setGeometry(100, 100, 1800, 1000)
323
+
324
+ # Create and set central widget
325
+ browser = SuperbrowserWidget()
326
+ window.setCentralWidget(browser)
327
+
328
+ window.show()
329
+ sys.exit(app.exec())