supervertaler 1.9.204__py3-none-any.whl → 1.9.205__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 +146 -35
- modules/ai_actions.py +14 -2
- modules/quicktrans.py +3 -0
- modules/termbase_entry_editor.py +9 -0
- modules/theme_manager.py +10 -1
- modules/translation_results_panel.py +6 -0
- modules/unified_prompt_manager_qt.py +206 -4
- modules/voice_dictation.py +9 -0
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/METADATA +1 -1
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/RECORD +14 -14
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/WHEEL +0 -0
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/entry_points.txt +0 -0
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/licenses/LICENSE +0 -0
- {supervertaler-1.9.204.dist-info → supervertaler-1.9.205.dist-info}/top_level.txt +0 -0
Supervertaler.py
CHANGED
|
@@ -9544,6 +9544,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
9544
9544
|
QPushButton:hover {
|
|
9545
9545
|
background-color: #2980b9;
|
|
9546
9546
|
}
|
|
9547
|
+
QPushButton:focus {
|
|
9548
|
+
outline: none;
|
|
9549
|
+
}
|
|
9547
9550
|
""")
|
|
9548
9551
|
extract_btn.clicked.connect(self._on_extract_images)
|
|
9549
9552
|
header_layout.addWidget(extract_btn)
|
|
@@ -21190,6 +21193,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
21190
21193
|
QPushButton:hover:!checked {
|
|
21191
21194
|
background-color: #858585;
|
|
21192
21195
|
}
|
|
21196
|
+
QPushButton:focus {
|
|
21197
|
+
outline: none;
|
|
21198
|
+
}
|
|
21193
21199
|
""")
|
|
21194
21200
|
wysiwyg_btn.clicked.connect(lambda: self.toggle_tag_view(False, None))
|
|
21195
21201
|
view_mode_group.addButton(wysiwyg_btn, 0)
|
|
@@ -21216,6 +21222,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
21216
21222
|
QPushButton:hover:!checked {
|
|
21217
21223
|
background-color: #858585;
|
|
21218
21224
|
}
|
|
21225
|
+
QPushButton:focus {
|
|
21226
|
+
outline: none;
|
|
21227
|
+
}
|
|
21219
21228
|
""")
|
|
21220
21229
|
tags_btn.clicked.connect(lambda: self.toggle_tag_view(True, None))
|
|
21221
21230
|
view_mode_group.addButton(tags_btn, 1)
|
|
@@ -21273,6 +21282,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
21273
21282
|
QPushButton:checked {
|
|
21274
21283
|
background-color: #2E7D32;
|
|
21275
21284
|
}
|
|
21285
|
+
QPushButton:focus {
|
|
21286
|
+
outline: none;
|
|
21287
|
+
}
|
|
21276
21288
|
""")
|
|
21277
21289
|
alwayson_btn.setToolTip("Toggle always-on voice listening\n\nWhen ON: Listens continuously for voice commands\nNo need to press F9")
|
|
21278
21290
|
alwayson_btn.clicked.connect(lambda checked: self._toggle_alwayson_from_grid_btn(checked, alwayson_btn))
|
|
@@ -22032,6 +22044,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
22032
22044
|
QPushButton:pressed {
|
|
22033
22045
|
background-color: #1565C0;
|
|
22034
22046
|
}
|
|
22047
|
+
QPushButton:focus {
|
|
22048
|
+
outline: none;
|
|
22049
|
+
}
|
|
22035
22050
|
""")
|
|
22036
22051
|
self.scroll_up_btn.setToolTip("Scroll up one row (Precision scroll)")
|
|
22037
22052
|
self.scroll_up_btn.clicked.connect(lambda: self.precision_scroll(-1))
|
|
@@ -22058,6 +22073,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
22058
22073
|
QPushButton:pressed {
|
|
22059
22074
|
background-color: #1565C0;
|
|
22060
22075
|
}
|
|
22076
|
+
QPushButton:focus {
|
|
22077
|
+
outline: none;
|
|
22078
|
+
}
|
|
22061
22079
|
""")
|
|
22062
22080
|
self.scroll_down_btn.setToolTip("Scroll down one row (Precision scroll)")
|
|
22063
22081
|
self.scroll_down_btn.clicked.connect(lambda: self.precision_scroll(1))
|
|
@@ -24678,6 +24696,11 @@ class SupervertalerQt(QMainWindow):
|
|
|
24678
24696
|
# Set as current project and load into grid
|
|
24679
24697
|
self.current_project = project
|
|
24680
24698
|
self.current_document_path = file_path # Store document path
|
|
24699
|
+
|
|
24700
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
24701
|
+
# This prevents old segments from being saved instead of new ones
|
|
24702
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
24703
|
+
|
|
24681
24704
|
self.load_segments_to_grid()
|
|
24682
24705
|
|
|
24683
24706
|
# Initialize TM for this project
|
|
@@ -24912,14 +24935,18 @@ class SupervertalerQt(QMainWindow):
|
|
|
24912
24935
|
# Set as current project and load into grid
|
|
24913
24936
|
self.current_project = project
|
|
24914
24937
|
self.current_document_path = file_path
|
|
24938
|
+
|
|
24939
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
24940
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
24941
|
+
|
|
24915
24942
|
self.load_segments_to_grid()
|
|
24916
|
-
|
|
24943
|
+
|
|
24917
24944
|
# Initialize TM for this project
|
|
24918
24945
|
self.initialize_tm_database()
|
|
24919
|
-
|
|
24946
|
+
|
|
24920
24947
|
# Initialize spellcheck for target language
|
|
24921
24948
|
self._initialize_spellcheck_for_target_language(target_lang)
|
|
24922
|
-
|
|
24949
|
+
|
|
24923
24950
|
# Update status
|
|
24924
24951
|
empty_count = sum(1 for seg in segments if not seg.source.strip())
|
|
24925
24952
|
file_type = "Markdown file" if is_markdown else "text file"
|
|
@@ -24979,6 +25006,8 @@ class SupervertalerQt(QMainWindow):
|
|
|
24979
25006
|
project.original_txt_path = file_path
|
|
24980
25007
|
self.current_project = project
|
|
24981
25008
|
self.current_document_path = file_path
|
|
25009
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
25010
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
24982
25011
|
self.load_segments_to_grid()
|
|
24983
25012
|
self.initialize_tm_database()
|
|
24984
25013
|
self.log(f"✓ Loaded {len(segments)} lines from text file")
|
|
@@ -26307,10 +26336,13 @@ class SupervertalerQt(QMainWindow):
|
|
|
26307
26336
|
# Set as current project
|
|
26308
26337
|
self.current_project = project
|
|
26309
26338
|
self.current_document_path = folder_path
|
|
26310
|
-
|
|
26339
|
+
|
|
26340
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
26341
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
26342
|
+
|
|
26311
26343
|
# Load into grid
|
|
26312
26344
|
self.load_segments_to_grid()
|
|
26313
|
-
|
|
26345
|
+
|
|
26314
26346
|
# Initialize TM
|
|
26315
26347
|
self.initialize_tm_database()
|
|
26316
26348
|
|
|
@@ -27183,10 +27215,14 @@ class SupervertalerQt(QMainWindow):
|
|
|
27183
27215
|
# Update UI
|
|
27184
27216
|
self.project_file_path = None
|
|
27185
27217
|
self.project_modified = True
|
|
27218
|
+
|
|
27219
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
27220
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
27221
|
+
|
|
27186
27222
|
self.update_window_title()
|
|
27187
27223
|
self.load_segments_to_grid()
|
|
27188
27224
|
self.initialize_tm_database()
|
|
27189
|
-
|
|
27225
|
+
|
|
27190
27226
|
# Deactivate all resources for new project, then auto-activate language-matching ones
|
|
27191
27227
|
self._deactivate_all_resources_for_new_project()
|
|
27192
27228
|
|
|
@@ -27199,7 +27235,7 @@ class SupervertalerQt(QMainWindow):
|
|
|
27199
27235
|
# If smart formatting was used, auto-enable Tags view so user sees the tags
|
|
27200
27236
|
if self.memoq_smart_formatting:
|
|
27201
27237
|
self._enable_tag_view_after_import()
|
|
27202
|
-
|
|
27238
|
+
|
|
27203
27239
|
self.log(f"✓ Imported memoQ bilingual DOCX: {len(source_segments)} segments from {Path(file_path).name}")
|
|
27204
27240
|
|
|
27205
27241
|
# Store current document path for AI Assistant
|
|
@@ -27692,10 +27728,14 @@ class SupervertalerQt(QMainWindow):
|
|
|
27692
27728
|
# Update UI
|
|
27693
27729
|
self.project_file_path = None
|
|
27694
27730
|
self.project_modified = True
|
|
27731
|
+
|
|
27732
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
27733
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
27734
|
+
|
|
27695
27735
|
self.update_window_title()
|
|
27696
27736
|
self.load_segments_to_grid()
|
|
27697
27737
|
self.initialize_tm_database()
|
|
27698
|
-
|
|
27738
|
+
|
|
27699
27739
|
# Deactivate all resources for new project, then auto-activate language-matching ones
|
|
27700
27740
|
self._deactivate_all_resources_for_new_project()
|
|
27701
27741
|
|
|
@@ -27971,10 +28011,14 @@ class SupervertalerQt(QMainWindow):
|
|
|
27971
28011
|
# Update UI
|
|
27972
28012
|
self.project_file_path = None
|
|
27973
28013
|
self.project_modified = True
|
|
28014
|
+
|
|
28015
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
28016
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
28017
|
+
|
|
27974
28018
|
self.update_window_title()
|
|
27975
28019
|
self.load_segments_to_grid()
|
|
27976
28020
|
self.initialize_tm_database()
|
|
27977
|
-
|
|
28021
|
+
|
|
27978
28022
|
# Deactivate all resources for new project, then auto-activate language-matching ones
|
|
27979
28023
|
self._deactivate_all_resources_for_new_project()
|
|
27980
28024
|
|
|
@@ -28192,6 +28236,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
28192
28236
|
# Store Trados source path in project for persistence across saves
|
|
28193
28237
|
self.current_project.trados_source_path = file_path
|
|
28194
28238
|
|
|
28239
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
28240
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
28241
|
+
|
|
28195
28242
|
# Sync global language settings with imported project languages
|
|
28196
28243
|
self.source_language = source_lang
|
|
28197
28244
|
self.target_language = target_lang
|
|
@@ -28556,6 +28603,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
28556
28603
|
self.sdlppx_source_file = file_path
|
|
28557
28604
|
self.current_project.sdlppx_source_path = file_path
|
|
28558
28605
|
|
|
28606
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
28607
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
28608
|
+
|
|
28559
28609
|
# Sync global language settings with imported project languages
|
|
28560
28610
|
self.source_language = source_lang
|
|
28561
28611
|
self.target_language = target_lang
|
|
@@ -28892,6 +28942,9 @@ class SupervertalerQt(QMainWindow):
|
|
|
28892
28942
|
# Store Phrase source path in project for persistence across saves
|
|
28893
28943
|
self.current_project.phrase_source_path = file_path
|
|
28894
28944
|
|
|
28945
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
28946
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
28947
|
+
|
|
28895
28948
|
# Sync global language settings with imported project languages
|
|
28896
28949
|
self.source_language = source_lang
|
|
28897
28950
|
self.target_language = target_lang
|
|
@@ -29194,20 +29247,23 @@ class SupervertalerQt(QMainWindow):
|
|
|
29194
29247
|
dejavu_row_index=seg_data.row_index,
|
|
29195
29248
|
)
|
|
29196
29249
|
self.current_project.segments.append(segment)
|
|
29197
|
-
|
|
29250
|
+
|
|
29251
|
+
# CRITICAL: Update _original_segment_order for new import
|
|
29252
|
+
self._original_segment_order = self.current_project.segments.copy()
|
|
29253
|
+
|
|
29198
29254
|
# Update UI
|
|
29199
29255
|
self.project_file_path = None
|
|
29200
29256
|
self.project_modified = True
|
|
29201
29257
|
self.update_window_title()
|
|
29202
29258
|
self.load_segments_to_grid()
|
|
29203
29259
|
self.initialize_tm_database()
|
|
29204
|
-
|
|
29260
|
+
|
|
29205
29261
|
# Auto-resize rows for better initial display
|
|
29206
29262
|
self.auto_resize_rows()
|
|
29207
|
-
|
|
29263
|
+
|
|
29208
29264
|
# Initialize spellcheck for target language
|
|
29209
29265
|
self._initialize_spellcheck_for_target_language(target_lang)
|
|
29210
|
-
|
|
29266
|
+
|
|
29211
29267
|
self.log(f"✓ Imported Déjà Vu X3 bilingual RTF: {len(segments_data)} segments from {Path(file_path).name}")
|
|
29212
29268
|
|
|
29213
29269
|
# Store current document path for AI Assistant
|
|
@@ -44605,12 +44661,25 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
|
|
|
44605
44661
|
|
|
44606
44662
|
translator = deepl.Translator(api_key)
|
|
44607
44663
|
|
|
44608
|
-
#
|
|
44609
|
-
|
|
44664
|
+
# Map full language names to ISO codes
|
|
44665
|
+
lang_name_to_code = {
|
|
44666
|
+
'english': 'en', 'dutch': 'nl', 'german': 'de', 'french': 'fr',
|
|
44667
|
+
'spanish': 'es', 'italian': 'it', 'portuguese': 'pt', 'russian': 'ru',
|
|
44668
|
+
'chinese': 'zh', 'japanese': 'ja', 'korean': 'ko', 'arabic': 'ar',
|
|
44669
|
+
'polish': 'pl', 'swedish': 'sv', 'norwegian': 'no', 'danish': 'da',
|
|
44670
|
+
'finnish': 'fi', 'greek': 'el', 'turkish': 'tr', 'czech': 'cs',
|
|
44671
|
+
'hungarian': 'hu', 'romanian': 'ro', 'bulgarian': 'bg', 'ukrainian': 'uk',
|
|
44672
|
+
}
|
|
44673
|
+
|
|
44674
|
+
# Convert source language - try name mapping first, then code extraction
|
|
44675
|
+
src_lower = source_lang.lower().strip()
|
|
44676
|
+
src_base = lang_name_to_code.get(src_lower, src_lower.split('-')[0].split('_')[0])
|
|
44677
|
+
src_code = src_base.upper()
|
|
44610
44678
|
|
|
44611
|
-
# Convert target language
|
|
44612
|
-
|
|
44613
|
-
|
|
44679
|
+
# Convert target language - try name mapping first, then handle DeepL variants
|
|
44680
|
+
tgt_lower = target_lang.lower().strip()
|
|
44681
|
+
tgt_base = lang_name_to_code.get(tgt_lower, tgt_lower)
|
|
44682
|
+
tgt_upper = tgt_base.upper().replace('_', '-')
|
|
44614
44683
|
|
|
44615
44684
|
# DeepL target language mapping - some require specific variants
|
|
44616
44685
|
deepl_target_map = {
|
|
@@ -44656,19 +44725,33 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
|
|
|
44656
44725
|
"""Call Microsoft Azure Translator API"""
|
|
44657
44726
|
try:
|
|
44658
44727
|
import requests
|
|
44659
|
-
|
|
44728
|
+
|
|
44660
44729
|
api_keys = self.load_api_keys()
|
|
44661
44730
|
if not api_key:
|
|
44662
44731
|
api_key = api_keys.get("microsoft_translate") or api_keys.get("azure_translate")
|
|
44663
44732
|
if not region:
|
|
44664
44733
|
region = api_keys.get("microsoft_translate_region") or api_keys.get("azure_region") or "global"
|
|
44665
|
-
|
|
44734
|
+
|
|
44666
44735
|
if not api_key:
|
|
44667
44736
|
return "[Microsoft Translator requires API key]"
|
|
44668
|
-
|
|
44669
|
-
#
|
|
44670
|
-
|
|
44671
|
-
|
|
44737
|
+
|
|
44738
|
+
# Map full language names to ISO codes
|
|
44739
|
+
lang_name_to_code = {
|
|
44740
|
+
'english': 'en', 'dutch': 'nl', 'german': 'de', 'french': 'fr',
|
|
44741
|
+
'spanish': 'es', 'italian': 'it', 'portuguese': 'pt', 'russian': 'ru',
|
|
44742
|
+
'chinese': 'zh', 'japanese': 'ja', 'korean': 'ko', 'arabic': 'ar',
|
|
44743
|
+
'polish': 'pl', 'swedish': 'sv', 'norwegian': 'no', 'danish': 'da',
|
|
44744
|
+
'finnish': 'fi', 'greek': 'el', 'turkish': 'tr', 'czech': 'cs',
|
|
44745
|
+
'hungarian': 'hu', 'romanian': 'ro', 'bulgarian': 'bg', 'ukrainian': 'uk',
|
|
44746
|
+
'hebrew': 'he', 'thai': 'th', 'vietnamese': 'vi', 'indonesian': 'id',
|
|
44747
|
+
}
|
|
44748
|
+
|
|
44749
|
+
# Convert language - try name mapping first, then code extraction
|
|
44750
|
+
src_lower = source_lang.lower().strip()
|
|
44751
|
+
tgt_lower = target_lang.lower().strip()
|
|
44752
|
+
|
|
44753
|
+
src_code = lang_name_to_code.get(src_lower, src_lower.split('-')[0].split('_')[0])
|
|
44754
|
+
tgt_code = lang_name_to_code.get(tgt_lower, tgt_lower.split('-')[0].split('_')[0])
|
|
44672
44755
|
|
|
44673
44756
|
# Microsoft Translator API v3.0
|
|
44674
44757
|
endpoint = f"https://api.cognitive.microsofttranslator.com/translate"
|
|
@@ -44756,17 +44839,30 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
|
|
|
44756
44839
|
"""Call ModernMT API"""
|
|
44757
44840
|
try:
|
|
44758
44841
|
import requests
|
|
44759
|
-
|
|
44842
|
+
|
|
44760
44843
|
api_keys = self.load_api_keys()
|
|
44761
44844
|
if not api_key:
|
|
44762
44845
|
api_key = api_keys.get("modernmt")
|
|
44763
|
-
|
|
44846
|
+
|
|
44764
44847
|
if not api_key:
|
|
44765
44848
|
return "[ModernMT requires API key]"
|
|
44766
|
-
|
|
44767
|
-
#
|
|
44768
|
-
|
|
44769
|
-
|
|
44849
|
+
|
|
44850
|
+
# Map full language names to ISO codes
|
|
44851
|
+
lang_name_to_code = {
|
|
44852
|
+
'english': 'en', 'dutch': 'nl', 'german': 'de', 'french': 'fr',
|
|
44853
|
+
'spanish': 'es', 'italian': 'it', 'portuguese': 'pt', 'russian': 'ru',
|
|
44854
|
+
'chinese': 'zh', 'japanese': 'ja', 'korean': 'ko', 'arabic': 'ar',
|
|
44855
|
+
'polish': 'pl', 'swedish': 'sv', 'norwegian': 'no', 'danish': 'da',
|
|
44856
|
+
'finnish': 'fi', 'greek': 'el', 'turkish': 'tr', 'czech': 'cs',
|
|
44857
|
+
'hungarian': 'hu', 'romanian': 'ro', 'bulgarian': 'bg', 'ukrainian': 'uk',
|
|
44858
|
+
}
|
|
44859
|
+
|
|
44860
|
+
# Convert language - try name mapping first, then code extraction
|
|
44861
|
+
src_lower = source_lang.lower().strip()
|
|
44862
|
+
tgt_lower = target_lang.lower().strip()
|
|
44863
|
+
|
|
44864
|
+
src_code = lang_name_to_code.get(src_lower, src_lower.split('-')[0].split('_')[0])
|
|
44865
|
+
tgt_code = lang_name_to_code.get(tgt_lower, tgt_lower.split('-')[0].split('_')[0])
|
|
44770
44866
|
|
|
44771
44867
|
# ModernMT API endpoint
|
|
44772
44868
|
url = "https://api.modernmt.com/translate"
|
|
@@ -44795,14 +44891,29 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
|
|
|
44795
44891
|
"""Call MyMemory Translation API (free tier available, simple REST API)"""
|
|
44796
44892
|
try:
|
|
44797
44893
|
import requests
|
|
44798
|
-
|
|
44894
|
+
|
|
44799
44895
|
# MyMemory is free, but API key provides higher limits
|
|
44800
44896
|
api_keys = self.load_api_keys()
|
|
44801
44897
|
api_key = api_key or api_keys.get("mymemory") # Optional, works without key
|
|
44802
|
-
|
|
44803
|
-
#
|
|
44804
|
-
|
|
44805
|
-
|
|
44898
|
+
|
|
44899
|
+
# Map full language names to ISO codes
|
|
44900
|
+
lang_name_to_code = {
|
|
44901
|
+
'english': 'en', 'dutch': 'nl', 'german': 'de', 'french': 'fr',
|
|
44902
|
+
'spanish': 'es', 'italian': 'it', 'portuguese': 'pt', 'russian': 'ru',
|
|
44903
|
+
'chinese': 'zh', 'japanese': 'ja', 'korean': 'ko', 'arabic': 'ar',
|
|
44904
|
+
'polish': 'pl', 'swedish': 'sv', 'norwegian': 'no', 'danish': 'da',
|
|
44905
|
+
'finnish': 'fi', 'greek': 'el', 'turkish': 'tr', 'czech': 'cs',
|
|
44906
|
+
'hungarian': 'hu', 'romanian': 'ro', 'bulgarian': 'bg', 'ukrainian': 'uk',
|
|
44907
|
+
'hebrew': 'he', 'thai': 'th', 'vietnamese': 'vi', 'indonesian': 'id',
|
|
44908
|
+
'malay': 'ms', 'hindi': 'hi', 'bengali': 'bn', 'tamil': 'ta',
|
|
44909
|
+
}
|
|
44910
|
+
|
|
44911
|
+
# Convert language - try name mapping first, then code extraction
|
|
44912
|
+
src_lower = source_lang.lower().strip()
|
|
44913
|
+
tgt_lower = target_lang.lower().strip()
|
|
44914
|
+
|
|
44915
|
+
src_code = lang_name_to_code.get(src_lower, src_lower.split('-')[0].split('_')[0])
|
|
44916
|
+
tgt_code = lang_name_to_code.get(tgt_lower, tgt_lower.split('-')[0].split('_')[0])
|
|
44806
44917
|
|
|
44807
44918
|
# MyMemory API endpoint
|
|
44808
44919
|
url = "https://api.mymemory.translated.net/get"
|
modules/ai_actions.py
CHANGED
|
@@ -168,9 +168,10 @@ class AIActionSystem:
|
|
|
168
168
|
|
|
169
169
|
except json.JSONDecodeError as e:
|
|
170
170
|
self.log(f"✗ Failed to parse action parameters: {e}")
|
|
171
|
+
self.log(f"[DEBUG] Raw params_str: {params_str[:500]}...") # Log what we tried to parse
|
|
171
172
|
action_results.append({
|
|
172
173
|
'action': action_name,
|
|
173
|
-
'params': params_str,
|
|
174
|
+
'params': params_str[:200], # Truncate for display
|
|
174
175
|
'success': False,
|
|
175
176
|
'error': f"Invalid JSON parameters: {e}"
|
|
176
177
|
})
|
|
@@ -325,7 +326,15 @@ class AIActionSystem:
|
|
|
325
326
|
content = params.get('content')
|
|
326
327
|
|
|
327
328
|
if not name or not content:
|
|
328
|
-
|
|
329
|
+
# Log what we actually received for debugging
|
|
330
|
+
self.log(f"[DEBUG] create_prompt received params: {params}")
|
|
331
|
+
self.log(f"[DEBUG] name={repr(name)}, content={repr(content)[:100] if content else None}")
|
|
332
|
+
missing = []
|
|
333
|
+
if not name:
|
|
334
|
+
missing.append("name")
|
|
335
|
+
if not content:
|
|
336
|
+
missing.append("content")
|
|
337
|
+
raise ValueError(f"Missing required parameters: {', '.join(missing)}. Received keys: {list(params.keys())}")
|
|
329
338
|
|
|
330
339
|
# Build relative path
|
|
331
340
|
folder = params.get('folder', '')
|
|
@@ -960,5 +969,8 @@ PARAMS: {
|
|
|
960
969
|
output += "\n"
|
|
961
970
|
else:
|
|
962
971
|
output += f"\n✗ **{action_name}**: {result['error']}\n"
|
|
972
|
+
# Show hint for common errors
|
|
973
|
+
if 'Missing required parameters' in result['error']:
|
|
974
|
+
output += " _Hint: The AI may not have generated the correct format. Try clicking the button again._\n"
|
|
963
975
|
|
|
964
976
|
return output
|
modules/quicktrans.py
CHANGED
modules/termbase_entry_editor.py
CHANGED
|
@@ -447,6 +447,9 @@ class TermbaseEntryEditor(QDialog):
|
|
|
447
447
|
QPushButton:hover {
|
|
448
448
|
background-color: #d32f2f;
|
|
449
449
|
}
|
|
450
|
+
QPushButton:focus {
|
|
451
|
+
outline: none;
|
|
452
|
+
}
|
|
450
453
|
""")
|
|
451
454
|
self.delete_btn.clicked.connect(self.delete_term)
|
|
452
455
|
buttons_layout.addWidget(self.delete_btn)
|
|
@@ -465,6 +468,9 @@ class TermbaseEntryEditor(QDialog):
|
|
|
465
468
|
QPushButton:hover {
|
|
466
469
|
background-color: #e0e0e0;
|
|
467
470
|
}
|
|
471
|
+
QPushButton:focus {
|
|
472
|
+
outline: none;
|
|
473
|
+
}
|
|
468
474
|
""")
|
|
469
475
|
self.cancel_btn.clicked.connect(self.reject)
|
|
470
476
|
buttons_layout.addWidget(self.cancel_btn)
|
|
@@ -483,6 +489,9 @@ class TermbaseEntryEditor(QDialog):
|
|
|
483
489
|
QPushButton:hover {
|
|
484
490
|
background-color: #45a049;
|
|
485
491
|
}
|
|
492
|
+
QPushButton:focus {
|
|
493
|
+
outline: none;
|
|
494
|
+
}
|
|
486
495
|
""")
|
|
487
496
|
self.save_btn.clicked.connect(self.save_term)
|
|
488
497
|
buttons_layout.addWidget(self.save_btn)
|
modules/theme_manager.py
CHANGED
|
@@ -370,7 +370,16 @@ class ThemeManager:
|
|
|
370
370
|
QPushButton:disabled {{
|
|
371
371
|
color: {theme.text_disabled};
|
|
372
372
|
}}
|
|
373
|
-
|
|
373
|
+
|
|
374
|
+
/* Remove focus rectangles from buttons */
|
|
375
|
+
QPushButton:focus {{
|
|
376
|
+
outline: none;
|
|
377
|
+
}}
|
|
378
|
+
|
|
379
|
+
QToolButton:focus {{
|
|
380
|
+
outline: none;
|
|
381
|
+
}}
|
|
382
|
+
|
|
374
383
|
/* Combo boxes */
|
|
375
384
|
QComboBox {{
|
|
376
385
|
background-color: {theme.base};
|
|
@@ -1190,6 +1190,9 @@ class TranslationResultsPanel(QWidget):
|
|
|
1190
1190
|
QPushButton:hover {
|
|
1191
1191
|
background-color: #0b7dda;
|
|
1192
1192
|
}
|
|
1193
|
+
QPushButton:focus {
|
|
1194
|
+
outline: none;
|
|
1195
|
+
}
|
|
1193
1196
|
""")
|
|
1194
1197
|
self.termbase_refresh_btn.setFixedHeight(20)
|
|
1195
1198
|
self.termbase_refresh_btn.setToolTip("Refresh entry from database")
|
|
@@ -1210,6 +1213,9 @@ class TranslationResultsPanel(QWidget):
|
|
|
1210
1213
|
QPushButton:hover {
|
|
1211
1214
|
background-color: #45a049;
|
|
1212
1215
|
}
|
|
1216
|
+
QPushButton:focus {
|
|
1217
|
+
outline: none;
|
|
1218
|
+
}
|
|
1213
1219
|
""")
|
|
1214
1220
|
self.termbase_edit_btn.setFixedHeight(20)
|
|
1215
1221
|
self.termbase_edit_btn.clicked.connect(self._on_edit_termbase_entry)
|
|
@@ -595,6 +595,10 @@ class UnifiedPromptManagerQt:
|
|
|
595
595
|
log_callback=self.log_message
|
|
596
596
|
)
|
|
597
597
|
|
|
598
|
+
# Context inclusion toggles for AI Assistant
|
|
599
|
+
self.include_tm_data = False
|
|
600
|
+
self.include_termbase_data = False
|
|
601
|
+
|
|
598
602
|
self._init_llm_client()
|
|
599
603
|
self._load_conversation_history()
|
|
600
604
|
self._load_persisted_attachments()
|
|
@@ -824,6 +828,9 @@ class UnifiedPromptManagerQt:
|
|
|
824
828
|
QPushButton:pressed {
|
|
825
829
|
background-color: #0D47A1;
|
|
826
830
|
}
|
|
831
|
+
QPushButton:focus {
|
|
832
|
+
outline: none;
|
|
833
|
+
}
|
|
827
834
|
""")
|
|
828
835
|
action_btn.clicked.connect(self._analyze_and_generate)
|
|
829
836
|
layout.addWidget(action_btn, 0)
|
|
@@ -1046,14 +1053,16 @@ class UnifiedPromptManagerQt:
|
|
|
1046
1053
|
"Click to include TM data"
|
|
1047
1054
|
)
|
|
1048
1055
|
self.context_tms.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
1056
|
+
self.context_tms.mousePressEvent = lambda e: self._toggle_tm_inclusion()
|
|
1049
1057
|
content_layout.addWidget(self.context_tms)
|
|
1050
|
-
|
|
1058
|
+
|
|
1051
1059
|
# Termbases
|
|
1052
1060
|
self.context_termbases = self._create_context_section(
|
|
1053
1061
|
"📚 Termbases",
|
|
1054
1062
|
"Click to include termbase data"
|
|
1055
1063
|
)
|
|
1056
1064
|
self.context_termbases.setCursor(Qt.CursorShape.PointingHandCursor)
|
|
1065
|
+
self.context_termbases.mousePressEvent = lambda e: self._toggle_termbase_inclusion()
|
|
1057
1066
|
content_layout.addWidget(self.context_termbases)
|
|
1058
1067
|
|
|
1059
1068
|
content_layout.addStretch()
|
|
@@ -1094,6 +1103,95 @@ class UnifiedPromptManagerQt:
|
|
|
1094
1103
|
|
|
1095
1104
|
return frame
|
|
1096
1105
|
|
|
1106
|
+
def _toggle_tm_inclusion(self):
|
|
1107
|
+
"""Toggle inclusion of TM data in AI context"""
|
|
1108
|
+
self.include_tm_data = not self.include_tm_data
|
|
1109
|
+
self._update_tm_section_display()
|
|
1110
|
+
|
|
1111
|
+
# Show feedback
|
|
1112
|
+
status = "enabled" if self.include_tm_data else "disabled"
|
|
1113
|
+
self._add_chat_message("system", f"💾 Translation Memory inclusion **{status}**")
|
|
1114
|
+
|
|
1115
|
+
def _toggle_termbase_inclusion(self):
|
|
1116
|
+
"""Toggle inclusion of termbase data in AI context"""
|
|
1117
|
+
self.include_termbase_data = not self.include_termbase_data
|
|
1118
|
+
self._update_termbase_section_display()
|
|
1119
|
+
|
|
1120
|
+
# Show feedback
|
|
1121
|
+
status = "enabled" if self.include_termbase_data else "disabled"
|
|
1122
|
+
self._add_chat_message("system", f"📚 Termbase inclusion **{status}**")
|
|
1123
|
+
|
|
1124
|
+
def _update_tm_section_display(self):
|
|
1125
|
+
"""Update TM section visual state"""
|
|
1126
|
+
if self.include_tm_data:
|
|
1127
|
+
self.context_tms.setStyleSheet("""
|
|
1128
|
+
QFrame {
|
|
1129
|
+
background-color: #E3F2FD;
|
|
1130
|
+
border: 2px solid #1976D2;
|
|
1131
|
+
border-radius: 5px;
|
|
1132
|
+
padding: 8px;
|
|
1133
|
+
}
|
|
1134
|
+
""")
|
|
1135
|
+
# Update description label
|
|
1136
|
+
for child in self.context_tms.findChildren(QLabel):
|
|
1137
|
+
if "Click to" in child.text() or "✓" in child.text():
|
|
1138
|
+
child.setText("✓ TM data will be included")
|
|
1139
|
+
child.setStyleSheet("color: #1976D2; font-size: 8pt; font-weight: bold;")
|
|
1140
|
+
break
|
|
1141
|
+
else:
|
|
1142
|
+
self.context_tms.setStyleSheet("""
|
|
1143
|
+
QFrame {
|
|
1144
|
+
background-color: #F5F5F5;
|
|
1145
|
+
border: 1px solid #E0E0E0;
|
|
1146
|
+
border-radius: 5px;
|
|
1147
|
+
padding: 8px;
|
|
1148
|
+
}
|
|
1149
|
+
QFrame:hover {
|
|
1150
|
+
background-color: #EEEEEE;
|
|
1151
|
+
border: 1px solid #BDBDBD;
|
|
1152
|
+
}
|
|
1153
|
+
""")
|
|
1154
|
+
for child in self.context_tms.findChildren(QLabel):
|
|
1155
|
+
if "✓" in child.text() or "Click to" in child.text():
|
|
1156
|
+
child.setText("Click to include TM data")
|
|
1157
|
+
child.setStyleSheet("color: #666; font-size: 8pt;")
|
|
1158
|
+
break
|
|
1159
|
+
|
|
1160
|
+
def _update_termbase_section_display(self):
|
|
1161
|
+
"""Update termbase section visual state"""
|
|
1162
|
+
if self.include_termbase_data:
|
|
1163
|
+
self.context_termbases.setStyleSheet("""
|
|
1164
|
+
QFrame {
|
|
1165
|
+
background-color: #E8F5E9;
|
|
1166
|
+
border: 2px solid #4CAF50;
|
|
1167
|
+
border-radius: 5px;
|
|
1168
|
+
padding: 8px;
|
|
1169
|
+
}
|
|
1170
|
+
""")
|
|
1171
|
+
for child in self.context_termbases.findChildren(QLabel):
|
|
1172
|
+
if "Click to" in child.text() or "✓" in child.text():
|
|
1173
|
+
child.setText("✓ Termbase data will be included")
|
|
1174
|
+
child.setStyleSheet("color: #4CAF50; font-size: 8pt; font-weight: bold;")
|
|
1175
|
+
break
|
|
1176
|
+
else:
|
|
1177
|
+
self.context_termbases.setStyleSheet("""
|
|
1178
|
+
QFrame {
|
|
1179
|
+
background-color: #F5F5F5;
|
|
1180
|
+
border: 1px solid #E0E0E0;
|
|
1181
|
+
border-radius: 5px;
|
|
1182
|
+
padding: 8px;
|
|
1183
|
+
}
|
|
1184
|
+
QFrame:hover {
|
|
1185
|
+
background-color: #EEEEEE;
|
|
1186
|
+
border: 1px solid #BDBDBD;
|
|
1187
|
+
}
|
|
1188
|
+
""")
|
|
1189
|
+
for child in self.context_termbases.findChildren(QLabel):
|
|
1190
|
+
if "✓" in child.text() or "Click to" in child.text():
|
|
1191
|
+
child.setText("Click to include termbase data")
|
|
1192
|
+
child.setStyleSheet("color: #666; font-size: 8pt;")
|
|
1193
|
+
break
|
|
1194
|
+
|
|
1097
1195
|
def _create_attached_files_section(self) -> QFrame:
|
|
1098
1196
|
"""Create expandable attached files section with view/remove buttons"""
|
|
1099
1197
|
frame = QFrame()
|
|
@@ -1125,6 +1223,9 @@ class UnifiedPromptManagerQt:
|
|
|
1125
1223
|
QPushButton:hover {
|
|
1126
1224
|
background-color: #E0E0E0;
|
|
1127
1225
|
}
|
|
1226
|
+
QPushButton:focus {
|
|
1227
|
+
outline: none;
|
|
1228
|
+
}
|
|
1128
1229
|
""")
|
|
1129
1230
|
self.attached_files_expand_btn.clicked.connect(self._toggle_attached_files)
|
|
1130
1231
|
header_layout.addWidget(self.attached_files_expand_btn)
|
|
@@ -1149,6 +1250,9 @@ class UnifiedPromptManagerQt:
|
|
|
1149
1250
|
QPushButton:hover {
|
|
1150
1251
|
background-color: #1565C0;
|
|
1151
1252
|
}
|
|
1253
|
+
QPushButton:focus {
|
|
1254
|
+
outline: none;
|
|
1255
|
+
}
|
|
1152
1256
|
""")
|
|
1153
1257
|
attach_btn.clicked.connect(self._attach_file)
|
|
1154
1258
|
header_layout.addWidget(attach_btn)
|
|
@@ -1253,6 +1357,9 @@ class UnifiedPromptManagerQt:
|
|
|
1253
1357
|
QPushButton:hover {
|
|
1254
1358
|
background-color: #1565C0;
|
|
1255
1359
|
}
|
|
1360
|
+
QPushButton:focus {
|
|
1361
|
+
outline: none;
|
|
1362
|
+
}
|
|
1256
1363
|
""")
|
|
1257
1364
|
view_btn.clicked.connect(lambda: self._view_file(file_data))
|
|
1258
1365
|
btn_layout.addWidget(view_btn)
|
|
@@ -1270,6 +1377,9 @@ class UnifiedPromptManagerQt:
|
|
|
1270
1377
|
QPushButton:hover {
|
|
1271
1378
|
background-color: #b71c1c;
|
|
1272
1379
|
}
|
|
1380
|
+
QPushButton:focus {
|
|
1381
|
+
outline: none;
|
|
1382
|
+
}
|
|
1273
1383
|
""")
|
|
1274
1384
|
remove_btn.clicked.connect(lambda: self._remove_file(file_data))
|
|
1275
1385
|
btn_layout.addWidget(remove_btn)
|
|
@@ -1405,6 +1515,9 @@ class UnifiedPromptManagerQt:
|
|
|
1405
1515
|
QPushButton:pressed {
|
|
1406
1516
|
background-color: #424242;
|
|
1407
1517
|
}
|
|
1518
|
+
QPushButton:focus {
|
|
1519
|
+
outline: none;
|
|
1520
|
+
}
|
|
1408
1521
|
""")
|
|
1409
1522
|
clear_btn.clicked.connect(self._clear_chat)
|
|
1410
1523
|
toolbar_layout.addWidget(clear_btn)
|
|
@@ -1456,6 +1569,9 @@ class UnifiedPromptManagerQt:
|
|
|
1456
1569
|
QPushButton:pressed {
|
|
1457
1570
|
background-color: #0D47A1;
|
|
1458
1571
|
}
|
|
1572
|
+
QPushButton:focus {
|
|
1573
|
+
outline: none;
|
|
1574
|
+
}
|
|
1459
1575
|
""")
|
|
1460
1576
|
send_btn.clicked.connect(self._send_chat_message)
|
|
1461
1577
|
input_layout.addWidget(send_btn)
|
|
@@ -3217,9 +3333,17 @@ If the text refers to figures (e.g., 'Figure 1A'), relevant images may be provid
|
|
|
3217
3333
|
PROJECT CONTEXT:
|
|
3218
3334
|
{context}
|
|
3219
3335
|
|
|
3220
|
-
|
|
3336
|
+
**CRITICAL INSTRUCTIONS:**
|
|
3337
|
+
1. You MUST output exactly ONE ACTION block in the following format
|
|
3338
|
+
2. The JSON MUST be valid and complete
|
|
3339
|
+
3. Both "name" and "content" are REQUIRED fields
|
|
3340
|
+
|
|
3341
|
+
**EXACT FORMAT TO USE:**
|
|
3221
3342
|
|
|
3222
|
-
ACTION:create_prompt PARAMS:{{"name": "
|
|
3343
|
+
ACTION:create_prompt PARAMS:{{"name": "Your Prompt Name Here", "content": "Your full prompt content here", "folder": "Project Prompts", "description": "Auto-generated prompt", "activate": true}}
|
|
3344
|
+
|
|
3345
|
+
**EXAMPLE:**
|
|
3346
|
+
ACTION:create_prompt PARAMS:{{"name": "Legal Translation EN-NL", "content": "You are an expert legal translator...\\n\\n# TERMINOLOGY\\n| Source | Target |\\n...", "folder": "Project Prompts", "description": "Auto-generated", "activate": true}}
|
|
3223
3347
|
|
|
3224
3348
|
Prompt must include:
|
|
3225
3349
|
|
|
@@ -3317,6 +3441,18 @@ Output complete ACTION."""
|
|
|
3317
3441
|
preview = file['content'][:200].replace('\n', ' ')
|
|
3318
3442
|
context_parts.append(f" Preview: {preview}...")
|
|
3319
3443
|
|
|
3444
|
+
# Translation Memory data (if enabled)
|
|
3445
|
+
if self.include_tm_data:
|
|
3446
|
+
tm_data = self._get_tm_context_data()
|
|
3447
|
+
if tm_data:
|
|
3448
|
+
context_parts.append(f"\n**Translation Memory Matches:**\n{tm_data}")
|
|
3449
|
+
|
|
3450
|
+
# Termbase data (if enabled)
|
|
3451
|
+
if self.include_termbase_data:
|
|
3452
|
+
tb_data = self._get_termbase_context_data()
|
|
3453
|
+
if tb_data:
|
|
3454
|
+
context_parts.append(f"\n**Termbase Entries:**\n{tb_data}")
|
|
3455
|
+
|
|
3320
3456
|
return "\n".join(context_parts) if context_parts else "No context available"
|
|
3321
3457
|
|
|
3322
3458
|
def _list_available_prompts(self) -> str:
|
|
@@ -3334,7 +3470,73 @@ Output complete ACTION."""
|
|
|
3334
3470
|
lines.append(f"... and {len(self.library.prompts) - 20} more")
|
|
3335
3471
|
|
|
3336
3472
|
return "\n".join(lines)
|
|
3337
|
-
|
|
3473
|
+
|
|
3474
|
+
def _get_tm_context_data(self) -> str:
|
|
3475
|
+
"""Get Translation Memory data for AI context"""
|
|
3476
|
+
try:
|
|
3477
|
+
if not hasattr(self.parent_app, 'tm_databases') or not self.parent_app.tm_databases:
|
|
3478
|
+
return "No translation memories loaded"
|
|
3479
|
+
|
|
3480
|
+
lines = []
|
|
3481
|
+
total_entries = 0
|
|
3482
|
+
|
|
3483
|
+
for tm_name, tm_db in self.parent_app.tm_databases.items():
|
|
3484
|
+
if hasattr(tm_db, 'entries'):
|
|
3485
|
+
count = len(tm_db.entries)
|
|
3486
|
+
total_entries += count
|
|
3487
|
+
lines.append(f"- **{tm_name}**: {count} entries")
|
|
3488
|
+
|
|
3489
|
+
# Show sample entries (first 10)
|
|
3490
|
+
for i, entry in enumerate(list(tm_db.entries.values())[:10]):
|
|
3491
|
+
if hasattr(entry, 'source') and hasattr(entry, 'target'):
|
|
3492
|
+
lines.append(f" {i+1}. {entry.source[:50]}... → {entry.target[:50]}...")
|
|
3493
|
+
|
|
3494
|
+
if not lines:
|
|
3495
|
+
return "Translation memories are empty"
|
|
3496
|
+
|
|
3497
|
+
return f"Total: {total_entries} TM entries\n" + "\n".join(lines)
|
|
3498
|
+
|
|
3499
|
+
except Exception as e:
|
|
3500
|
+
return f"Error loading TM data: {e}"
|
|
3501
|
+
|
|
3502
|
+
def _get_termbase_context_data(self) -> str:
|
|
3503
|
+
"""Get Termbase data for AI context"""
|
|
3504
|
+
try:
|
|
3505
|
+
if not hasattr(self.parent_app, 'termbases') or not self.parent_app.termbases:
|
|
3506
|
+
# Try to get termbase entries from the termbase manager
|
|
3507
|
+
if hasattr(self.parent_app, 'termbase_manager'):
|
|
3508
|
+
terms = self.parent_app.termbase_manager.get_all_terms()
|
|
3509
|
+
if terms:
|
|
3510
|
+
lines = [f"Total: {len(terms)} termbase entries\n"]
|
|
3511
|
+
for i, term in enumerate(terms[:50]): # First 50 terms
|
|
3512
|
+
source = term.get('source_term', term.get('source', ''))
|
|
3513
|
+
target = term.get('target_term', term.get('target', ''))
|
|
3514
|
+
if source and target:
|
|
3515
|
+
lines.append(f"| {source} | {target} |")
|
|
3516
|
+
return "\n".join(lines)
|
|
3517
|
+
return "No termbases loaded"
|
|
3518
|
+
|
|
3519
|
+
lines = []
|
|
3520
|
+
total_terms = 0
|
|
3521
|
+
|
|
3522
|
+
for tb_name, tb in self.parent_app.termbases.items():
|
|
3523
|
+
if hasattr(tb, 'terms'):
|
|
3524
|
+
count = len(tb.terms)
|
|
3525
|
+
total_terms += count
|
|
3526
|
+
lines.append(f"- **{tb_name}**: {count} terms")
|
|
3527
|
+
|
|
3528
|
+
# Show sample terms (first 20)
|
|
3529
|
+
for i, (source, target) in enumerate(list(tb.terms.items())[:20]):
|
|
3530
|
+
lines.append(f" | {source} | {target} |")
|
|
3531
|
+
|
|
3532
|
+
if not lines:
|
|
3533
|
+
return "Termbases are empty"
|
|
3534
|
+
|
|
3535
|
+
return f"Total: {total_terms} terms\n" + "\n".join(lines)
|
|
3536
|
+
|
|
3537
|
+
except Exception as e:
|
|
3538
|
+
return f"Error loading termbase data: {e}"
|
|
3539
|
+
|
|
3338
3540
|
def _attach_file(self):
|
|
3339
3541
|
"""Attach a file to the conversation"""
|
|
3340
3542
|
file_path, _ = QFileDialog.getOpenFileName(
|
modules/voice_dictation.py
CHANGED
|
@@ -240,6 +240,9 @@ class VoiceDictationWidget(QWidget):
|
|
|
240
240
|
QPushButton:disabled {
|
|
241
241
|
background-color: #BDBDBD;
|
|
242
242
|
}
|
|
243
|
+
QPushButton:focus {
|
|
244
|
+
outline: none;
|
|
245
|
+
}
|
|
243
246
|
""")
|
|
244
247
|
self.record_btn.clicked.connect(self.toggle_recording)
|
|
245
248
|
controls_layout.addWidget(self.record_btn)
|
|
@@ -345,6 +348,9 @@ class VoiceDictationWidget(QWidget):
|
|
|
345
348
|
QPushButton:hover {
|
|
346
349
|
background-color: #C62828;
|
|
347
350
|
}
|
|
351
|
+
QPushButton:focus {
|
|
352
|
+
outline: none;
|
|
353
|
+
}
|
|
348
354
|
""")
|
|
349
355
|
|
|
350
356
|
# Disable controls
|
|
@@ -380,6 +386,9 @@ class VoiceDictationWidget(QWidget):
|
|
|
380
386
|
QPushButton:hover {
|
|
381
387
|
background-color: #1976D2;
|
|
382
388
|
}
|
|
389
|
+
QPushButton:focus {
|
|
390
|
+
outline: none;
|
|
391
|
+
}
|
|
383
392
|
""")
|
|
384
393
|
|
|
385
394
|
# Start transcription
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: supervertaler
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.205
|
|
4
4
|
Summary: Professional AI-enhanced translation workbench with multi-LLM support, glossary system, TM, spellcheck, voice commands, and PyQt6 interface. Batteries included (core).
|
|
5
5
|
Home-page: https://supervertaler.com
|
|
6
6
|
Author: Michael Beijer
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Supervertaler.py,sha256=
|
|
1
|
+
Supervertaler.py,sha256=Q4pIpw6ZFn6DcIsX7oPk0iyZKRLg2HQFnIvhzZ98MrY,2403906
|
|
2
2
|
modules/__init__.py,sha256=G58XleS-EJ2sX4Kehm-3N2m618_W2Es0Kg8CW_eBG7g,327
|
|
3
|
-
modules/ai_actions.py,sha256=
|
|
3
|
+
modules/ai_actions.py,sha256=rU7h1TOkhPk_UaO6sxqj7V3FFUfo5Aj03Q6kSEllXyk,34688
|
|
4
4
|
modules/ai_attachment_manager.py,sha256=juZlrW3UPkIkcnj0SREgOQkQROLf0fcu3ShZcKXMxsI,11361
|
|
5
5
|
modules/ai_file_viewer_dialog.py,sha256=lKKqUUlOEVgHmmu6aRxqH7P6ds-7dRLk4ltDyjCwGxs,6246
|
|
6
6
|
modules/autofingers_engine.py,sha256=eJ7tBi7YJvTToe5hYTfnyGXB-qme_cHrOPZibaoR2Xw,17061
|
|
@@ -40,7 +40,7 @@ modules/prompt_assistant.py,sha256=shkZqNTvyQKNDO_9aFEu1_gN0zQq0fR5krXkWfnTR2Y,1
|
|
|
40
40
|
modules/prompt_library.py,sha256=t5w4cqB6_Sin4BQDVNALKpfB1EN_oaDeHFwlHxILLSY,26894
|
|
41
41
|
modules/prompt_library_migration.py,sha256=fv3RHhe2-EnH50XW5tyTWy0YP_KJ2EsESuTxR8klfmI,17639
|
|
42
42
|
modules/quick_access_sidebar.py,sha256=RPn5ssvYXlitNMWFZN9Yxv7So8u_z5RGNpHN6N-SFDI,10151
|
|
43
|
-
modules/quicktrans.py,sha256=
|
|
43
|
+
modules/quicktrans.py,sha256=uoEWb3MALfSR2nn07-hpBIsaQookqzcX9vAlKLGtOrE,26371
|
|
44
44
|
modules/ribbon_widget.py,sha256=QNGKxmit_oM5C5nJViadYYEzeRlIdIsla8Bzu_RNGO0,21990
|
|
45
45
|
modules/sdlppx_handler.py,sha256=o6Rj_T0B94toiYlvDDwMYLSz4q6kANgegFaDK5i3yhs,33538
|
|
46
46
|
modules/setup_wizard.py,sha256=7apNkeTcmMyw8pzJOWAmTOncxFvt3klOtmg-kKjQNgQ,13091
|
|
@@ -59,11 +59,11 @@ modules/superlookup.py,sha256=0SnIv-L8xNhAS5JuvoFPdp4BoScgACLFUB1fVwFe36Y,8980
|
|
|
59
59
|
modules/tag_cleaner.py,sha256=u7VOchIWzD4sAhFs3X1Vuo3hX6X72zESQ0AGZE83cYc,8703
|
|
60
60
|
modules/tag_manager.py,sha256=g66S0JSxdguN9AhWzZG3hsIz87Ul51wQ3c2wOCTZVSk,12789
|
|
61
61
|
modules/term_extractor.py,sha256=qPvKNCVXFTGEGwXNvvC0cfCmdb5c3WhzE38EOgKdKUI,11253
|
|
62
|
-
modules/termbase_entry_editor.py,sha256=
|
|
62
|
+
modules/termbase_entry_editor.py,sha256=V2IzVar8noU_SDhqkcZLg2NOtyAIhalSa5E6bLGcGUc,36070
|
|
63
63
|
modules/termbase_import_export.py,sha256=16IAY04IS_rgt0GH5UOUzUI5NoqAli4JMfMquxmFBm0,23552
|
|
64
64
|
modules/termbase_manager.py,sha256=XAVrz-wt8jKcjoD6ocHoXewY5PN0A0GeqFEctsv0jS8,48697
|
|
65
65
|
modules/termview_widget.py,sha256=FsNnSWh86PCnmKcC3fFJS8MJNdVvRpgE5e8-u4jAosY,55742
|
|
66
|
-
modules/theme_manager.py,sha256=
|
|
66
|
+
modules/theme_manager.py,sha256=EkiAviQ31ewzhMM0XaP4NkDJ2LZwRg8oXCy7BLQhc0k,18842
|
|
67
67
|
modules/tm_editor_dialog.py,sha256=AzGwq4QW641uFJdF8DljLTRRp4FLoYX3Pe4rlTjQWNg,3517
|
|
68
68
|
modules/tm_manager_qt.py,sha256=h2bvXkRuboHf_RRz9-5FX35GVRlpXgRDWeXyj1QWtPs,54406
|
|
69
69
|
modules/tm_metadata_manager.py,sha256=NTsaI_YjQnVOpU_scAwK9uR1Tcl9pzKD1GwLVy7sx2g,23590
|
|
@@ -73,16 +73,16 @@ modules/tmx_generator.py,sha256=pNkxwdMLvSRMMru0lkB1gvViIpg9BQy1EVhRbwoef3k,9426
|
|
|
73
73
|
modules/tracked_changes.py,sha256=S_BIEC6r7wVAwjG42aSy_RgH4KaMAC8GS5thEvqrYdE,39480
|
|
74
74
|
modules/trados_docx_handler.py,sha256=VPRAQ73cUHs_SEj6x81z1PmSxfjnwPBp9P4fXeK3KpQ,16363
|
|
75
75
|
modules/translation_memory.py,sha256=LnG8csZNL2GTHXT4zk0uecJEtvRc-MKwv7Pt7EX3s7s,28002
|
|
76
|
-
modules/translation_results_panel.py,sha256=
|
|
76
|
+
modules/translation_results_panel.py,sha256=HbYYjvRNqaJrJNLYLX-YanamMm6aRdLzLjn5rWIfk3U,92198
|
|
77
77
|
modules/translation_services.py,sha256=lyVpWuZK1wtVtYZMDMdLoq1DHBoSaeAnp-Yejb0TlVQ,10530
|
|
78
78
|
modules/unified_prompt_library.py,sha256=96u4WlMwnmmhD4uNJHZ-qVQj8v9_8dA2AVCWpBcwTrg,26006
|
|
79
|
-
modules/unified_prompt_manager_qt.py,sha256=
|
|
79
|
+
modules/unified_prompt_manager_qt.py,sha256=L96tgYpSLI0ZjD-R8eyxbwNYo_Vi1fyREFYriAR-Vlo,181992
|
|
80
80
|
modules/voice_commands.py,sha256=iBb-gjWxRMLhFH7-InSRjYJz1EIDBNA2Pog8V7TtJaY,38516
|
|
81
|
-
modules/voice_dictation.py,sha256=
|
|
81
|
+
modules/voice_dictation.py,sha256=7TlTTILSW4KwpTi1rDeKfvTwd5z3_XtNSzNIo35VAWU,16617
|
|
82
82
|
modules/voice_dictation_lite.py,sha256=jorY0BmWE-8VczbtGrWwt1zbnOctMoSlWOsQrcufBcc,9423
|
|
83
|
-
supervertaler-1.9.
|
|
84
|
-
supervertaler-1.9.
|
|
85
|
-
supervertaler-1.9.
|
|
86
|
-
supervertaler-1.9.
|
|
87
|
-
supervertaler-1.9.
|
|
88
|
-
supervertaler-1.9.
|
|
83
|
+
supervertaler-1.9.205.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
|
|
84
|
+
supervertaler-1.9.205.dist-info/METADATA,sha256=hX2ysmA8ur00DXX7Ua21H9t4Ct620QB1vAH7iwqVILs,5725
|
|
85
|
+
supervertaler-1.9.205.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
86
|
+
supervertaler-1.9.205.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
|
|
87
|
+
supervertaler-1.9.205.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
|
|
88
|
+
supervertaler-1.9.205.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|