supervertaler 1.9.109__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 +44945 -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 +1766 -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 +904 -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 +325 -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 +248 -0
  56. modules/tag_cleaner.py +260 -0
  57. modules/tag_manager.py +333 -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 +1161 -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 +670 -0
  73. modules/translation_results_panel.py +2134 -0
  74. modules/translation_services.py +282 -0
  75. modules/unified_prompt_library.py +656 -0
  76. modules/unified_prompt_manager_qt.py +3715 -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.109.dist-info/METADATA +788 -0
  81. supervertaler-1.9.109.dist-info/RECORD +85 -0
  82. supervertaler-1.9.109.dist-info/WHEEL +5 -0
  83. supervertaler-1.9.109.dist-info/entry_points.txt +2 -0
  84. supervertaler-1.9.109.dist-info/licenses/LICENSE +21 -0
  85. supervertaler-1.9.109.dist-info/top_level.txt +2 -0
@@ -0,0 +1,325 @@
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):
49
+ super().__init__(parent)
50
+ self.title = title
51
+ self.url = url
52
+ self.header_color = header_color
53
+ self.init_ui()
54
+
55
+ def init_ui(self):
56
+ """Initialize the chat column UI"""
57
+ layout = QVBoxLayout()
58
+ layout.setContentsMargins(0, 0, 0, 0)
59
+ layout.setSpacing(0)
60
+
61
+ # Tiny header label with provider name
62
+ header = QLabel(self.title)
63
+ header.setAlignment(Qt.AlignmentFlag.AlignCenter)
64
+ header.setStyleSheet(f"""
65
+ QLabel {{
66
+ background-color: {self.header_color};
67
+ color: white;
68
+ padding: 0px;
69
+ margin: 0px;
70
+ font-weight: bold;
71
+ font-size: 9px;
72
+ max-height: 20px;
73
+ min-height: 20px;
74
+ }}
75
+ """)
76
+
77
+ # URL bar for navigation
78
+ url_layout = QHBoxLayout()
79
+ url_layout.setContentsMargins(1, 1, 1, 1)
80
+
81
+ self.url_input = QLineEdit()
82
+ self.url_input.setText(self.url)
83
+ self.url_input.setPlaceholderText("Enter URL...")
84
+ self.url_input.returnPressed.connect(self.load_url)
85
+
86
+ reload_btn = QPushButton("↻")
87
+ reload_btn.setMaximumWidth(40)
88
+ reload_btn.setToolTip("Reload page")
89
+ reload_btn.clicked.connect(self.reload_page)
90
+
91
+ home_btn = QPushButton("⌂")
92
+ home_btn.setMaximumWidth(40)
93
+ home_btn.setToolTip("Go to home URL")
94
+ home_btn.clicked.connect(self.go_home)
95
+
96
+ url_layout.addWidget(self.url_input)
97
+ url_layout.addWidget(reload_btn)
98
+ url_layout.addWidget(home_btn)
99
+
100
+ # Web view with persistent profile
101
+ # Create or use persistent profile to save cookies and session data
102
+ profile_name = f"superbrowser_{self.title.lower()}"
103
+ self.profile = QWebEngineProfile(profile_name, self)
104
+
105
+ # Set persistent storage path (use same pattern as main app)
106
+ # Check if running in dev mode (private data folder)
107
+ dev_mode_marker = os.path.join(os.path.dirname(__file__), "..", ".supervertaler.local")
108
+ base_folder = "user_data_private" if os.path.exists(dev_mode_marker) else "user_data"
109
+
110
+ storage_path = os.path.join(os.path.dirname(__file__), "..", base_folder, "superbrowser_profiles", profile_name)
111
+ os.makedirs(storage_path, exist_ok=True)
112
+
113
+ # Clear potentially corrupted cache to prevent Chromium errors
114
+ _clear_corrupted_cache(storage_path)
115
+
116
+ self.profile.setPersistentStoragePath(storage_path)
117
+ self.profile.setCachePath(os.path.join(storage_path, "cache"))
118
+
119
+ # Enable persistent cookies
120
+ self.profile.setPersistentCookiesPolicy(QWebEngineProfile.PersistentCookiesPolicy.AllowPersistentCookies)
121
+
122
+ # Create web view with this profile
123
+ from PyQt6.QtWebEngineWidgets import QWebEngineView
124
+ from PyQt6.QtWebEngineCore import QWebEnginePage
125
+
126
+ page = QWebEnginePage(self.profile, self)
127
+ self.web_view = QWebEngineView()
128
+ self.web_view.setPage(page)
129
+ self.web_view.setUrl(QUrl(self.url))
130
+
131
+ # Update URL bar when page changes
132
+ self.web_view.urlChanged.connect(self.update_url_bar)
133
+
134
+ # Add to layout (tiny header, URL bar, then browser)
135
+ layout.addWidget(header)
136
+ layout.addLayout(url_layout)
137
+ layout.addWidget(self.web_view)
138
+
139
+ self.setLayout(layout)
140
+
141
+ def load_url(self):
142
+ """Load URL from input field"""
143
+ url_text = self.url_input.text().strip()
144
+ if not url_text.startswith(('http://', 'https://')):
145
+ url_text = 'https://' + url_text
146
+ self.web_view.setUrl(QUrl(url_text))
147
+
148
+ def reload_page(self):
149
+ """Reload the current page"""
150
+ self.web_view.reload()
151
+
152
+ def go_home(self):
153
+ """Go back to the home URL"""
154
+ self.web_view.setUrl(QUrl(self.url))
155
+
156
+ def update_url_bar(self, url):
157
+ """Update URL bar when page changes"""
158
+ self.url_input.setText(url.toString())
159
+
160
+
161
+ class SuperbrowserWidget(QWidget):
162
+ """
163
+ Superbrowser - Multi-Chat AI Browser Widget
164
+
165
+ Displays multiple AI chat interfaces side by side for easy comparison
166
+ and concurrent interaction with different AI models.
167
+ """
168
+
169
+ def __init__(self, parent=None):
170
+ super().__init__(parent)
171
+ self.parent_window = parent
172
+
173
+ # Default URLs for AI chat interfaces
174
+ self.chatgpt_url = "https://chatgpt.com/"
175
+ self.claude_url = "https://claude.ai/"
176
+ self.gemini_url = "https://gemini.google.com/"
177
+
178
+ self.init_ui()
179
+
180
+ def init_ui(self):
181
+ """Initialize the Superbrowser UI"""
182
+ main_layout = QVBoxLayout()
183
+ main_layout.setContentsMargins(5, 5, 5, 5)
184
+ main_layout.setSpacing(5)
185
+
186
+ # Compact title bar with toggle button
187
+ title_bar_layout = QHBoxLayout()
188
+ title_bar_layout.setContentsMargins(0, 0, 0, 0)
189
+
190
+ title_label = QLabel("🌐 Superbrowser - Multi-Chat AI Browser")
191
+ title_label.setStyleSheet("""
192
+ QLabel {
193
+ font-size: 12px;
194
+ font-weight: bold;
195
+ color: #2c3e50;
196
+ padding: 3px;
197
+ }
198
+ """)
199
+
200
+ description = QLabel(
201
+ "View and interact with ChatGPT, Claude, and Gemini side by side. "
202
+ "Perfect for comparing responses or maintaining multiple conversation threads."
203
+ )
204
+ description.setWordWrap(True)
205
+ description.setStyleSheet("color: #7f8c8d; padding: 3px; font-size: 10px;")
206
+
207
+ # Toggle button for configuration section
208
+ self.toggle_config_btn = QPushButton("▼ Hide Configuration")
209
+ self.toggle_config_btn.setMaximumWidth(150)
210
+ self.toggle_config_btn.setStyleSheet("""
211
+ QPushButton {
212
+ background-color: #3498db;
213
+ color: white;
214
+ border: none;
215
+ padding: 4px 8px;
216
+ font-size: 10px;
217
+ border-radius: 3px;
218
+ }
219
+ QPushButton:hover {
220
+ background-color: #2980b9;
221
+ }
222
+ """)
223
+ self.toggle_config_btn.clicked.connect(self.toggle_configuration)
224
+
225
+ title_bar_layout.addWidget(title_label)
226
+ title_bar_layout.addWidget(description, stretch=1)
227
+ title_bar_layout.addWidget(self.toggle_config_btn)
228
+
229
+ main_layout.addLayout(title_bar_layout)
230
+
231
+ # URL Configuration section (collapsible)
232
+ self.config_group = QGroupBox("🔧 Configuration")
233
+ self.config_group.setStyleSheet("QGroupBox { font-size: 10px; font-weight: bold; }")
234
+ config_layout = QFormLayout()
235
+
236
+ self.chatgpt_url_input = QLineEdit(self.chatgpt_url)
237
+ self.chatgpt_url_input.setStyleSheet("font-size: 10px;")
238
+ self.claude_url_input = QLineEdit(self.claude_url)
239
+ self.claude_url_input.setStyleSheet("font-size: 10px;")
240
+ self.gemini_url_input = QLineEdit(self.gemini_url)
241
+ self.gemini_url_input.setStyleSheet("font-size: 10px;")
242
+
243
+ config_layout.addRow("ChatGPT URL:", self.chatgpt_url_input)
244
+ config_layout.addRow("Claude URL:", self.claude_url_input)
245
+ config_layout.addRow("Gemini URL:", self.gemini_url_input)
246
+
247
+ update_btn = QPushButton("Update URLs")
248
+ update_btn.setStyleSheet("font-size: 10px; padding: 3px;")
249
+ update_btn.clicked.connect(self.update_urls)
250
+ config_layout.addRow("", update_btn)
251
+
252
+ self.config_group.setLayout(config_layout)
253
+ self.config_group.setMaximumHeight(150)
254
+ main_layout.addWidget(self.config_group)
255
+
256
+ # Splitter for resizable columns
257
+ splitter = QSplitter(Qt.Orientation.Horizontal)
258
+ splitter.setHandleWidth(3)
259
+
260
+ # Create chat columns
261
+ self.chatgpt_column = ChatColumn("ChatGPT", self.chatgpt_url, "#10a37f", self)
262
+ self.claude_column = ChatColumn("Claude", self.claude_url, "#c17c4f", self)
263
+ self.gemini_column = ChatColumn("Gemini", self.gemini_url, "#4285f4", self)
264
+
265
+ # Add columns to splitter
266
+ splitter.addWidget(self.chatgpt_column)
267
+ splitter.addWidget(self.claude_column)
268
+ splitter.addWidget(self.gemini_column)
269
+
270
+ # Set equal sizes for all columns
271
+ splitter.setSizes([600, 600, 600])
272
+
273
+ # Add splitter to main layout (takes most of the space)
274
+ main_layout.addWidget(splitter, stretch=1)
275
+
276
+ self.setLayout(main_layout)
277
+
278
+ def toggle_configuration(self):
279
+ """Toggle visibility of configuration section"""
280
+ if self.config_group.isVisible():
281
+ self.config_group.setVisible(False)
282
+ self.toggle_config_btn.setText("▶ Show Configuration")
283
+ else:
284
+ self.config_group.setVisible(True)
285
+ self.toggle_config_btn.setText("▼ Hide Configuration")
286
+
287
+ def update_urls(self):
288
+ """Update the URLs for all chat columns"""
289
+ self.chatgpt_url = self.chatgpt_url_input.text().strip() or self.chatgpt_url
290
+ self.claude_url = self.claude_url_input.text().strip() or self.claude_url
291
+ self.gemini_url = self.gemini_url_input.text().strip() or self.gemini_url
292
+
293
+ # Update the columns
294
+ self.chatgpt_column.url = self.chatgpt_url
295
+ self.claude_column.url = self.claude_url
296
+ self.gemini_column.url = self.gemini_url
297
+
298
+ # Reload to new URLs
299
+ self.chatgpt_column.go_home()
300
+ self.claude_column.go_home()
301
+ self.gemini_column.go_home()
302
+
303
+
304
+ # ============================================================================
305
+ # STANDALONE USAGE
306
+ # ============================================================================
307
+
308
+ if __name__ == "__main__":
309
+ import sys
310
+ from PyQt6.QtWidgets import QApplication, QMainWindow
311
+
312
+ app = QApplication(sys.argv)
313
+ app.setApplicationName("Superbrowser")
314
+
315
+ # Create main window for testing
316
+ window = QMainWindow()
317
+ window.setWindowTitle("Superbrowser - Multi-Chat AI Browser")
318
+ window.setGeometry(100, 100, 1800, 1000)
319
+
320
+ # Create and set central widget
321
+ browser = SuperbrowserWidget()
322
+ window.setCentralWidget(browser)
323
+
324
+ window.show()
325
+ sys.exit(app.exec())