supervertaler 1.9.116__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.
- Supervertaler.py +45720 -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 +1766 -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 +904 -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 +325 -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 +248 -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 +1161 -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 +670 -0
- modules/translation_results_panel.py +2134 -0
- modules/translation_services.py +282 -0
- modules/unified_prompt_library.py +656 -0
- modules/unified_prompt_manager_qt.py +3727 -0
- modules/voice_commands.py +920 -0
- modules/voice_dictation.py +477 -0
- modules/voice_dictation_lite.py +249 -0
- supervertaler-1.9.116.dist-info/METADATA +804 -0
- supervertaler-1.9.116.dist-info/RECORD +85 -0
- supervertaler-1.9.116.dist-info/WHEEL +5 -0
- supervertaler-1.9.116.dist-info/entry_points.txt +2 -0
- supervertaler-1.9.116.dist-info/licenses/LICENSE +21 -0
- supervertaler-1.9.116.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,904 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Keyboard Shortcut Manager for Supervertaler Qt
|
|
3
|
+
Centralized management of all keyboard shortcuts
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Dict, List, Optional, Tuple
|
|
9
|
+
from PyQt6.QtGui import QKeySequence
|
|
10
|
+
from PyQt6.QtCore import QSettings
|
|
11
|
+
|
|
12
|
+
class ShortcutManager:
|
|
13
|
+
"""Manages all keyboard shortcuts for Supervertaler"""
|
|
14
|
+
|
|
15
|
+
# Define all shortcuts with their categories, descriptions, and defaults
|
|
16
|
+
DEFAULT_SHORTCUTS = {
|
|
17
|
+
# File Operations
|
|
18
|
+
"file_new": {
|
|
19
|
+
"category": "File",
|
|
20
|
+
"description": "New Project",
|
|
21
|
+
"default": "Ctrl+N",
|
|
22
|
+
"action": "new_project"
|
|
23
|
+
},
|
|
24
|
+
"file_open": {
|
|
25
|
+
"category": "File",
|
|
26
|
+
"description": "Open Project",
|
|
27
|
+
"default": "Ctrl+O",
|
|
28
|
+
"action": "open_project"
|
|
29
|
+
},
|
|
30
|
+
"file_save": {
|
|
31
|
+
"category": "File",
|
|
32
|
+
"description": "Save Project",
|
|
33
|
+
"default": "Ctrl+S",
|
|
34
|
+
"action": "save_project"
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
"file_quit": {
|
|
38
|
+
"category": "File",
|
|
39
|
+
"description": "Quit Application",
|
|
40
|
+
"default": "Alt+F4",
|
|
41
|
+
"action": "close"
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
# Edit Operations
|
|
45
|
+
"edit_undo": {
|
|
46
|
+
"category": "Edit",
|
|
47
|
+
"description": "Undo",
|
|
48
|
+
"default": "Ctrl+Z",
|
|
49
|
+
"action": "undo"
|
|
50
|
+
},
|
|
51
|
+
"edit_redo": {
|
|
52
|
+
"category": "Edit",
|
|
53
|
+
"description": "Redo",
|
|
54
|
+
"default": "Ctrl+Y",
|
|
55
|
+
"action": "redo"
|
|
56
|
+
},
|
|
57
|
+
"edit_find": {
|
|
58
|
+
"category": "Edit",
|
|
59
|
+
"description": "Find",
|
|
60
|
+
"default": "Ctrl+F",
|
|
61
|
+
"action": "show_find_replace_dialog"
|
|
62
|
+
},
|
|
63
|
+
"edit_replace": {
|
|
64
|
+
"category": "Edit",
|
|
65
|
+
"description": "Replace",
|
|
66
|
+
"default": "Ctrl+H",
|
|
67
|
+
"action": "show_find_replace_dialog"
|
|
68
|
+
},
|
|
69
|
+
"edit_goto": {
|
|
70
|
+
"category": "Edit",
|
|
71
|
+
"description": "Go to Segment",
|
|
72
|
+
"default": "Ctrl+G",
|
|
73
|
+
"action": "show_goto_dialog"
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
# Translation Operations
|
|
77
|
+
"translate_current": {
|
|
78
|
+
"category": "Translation",
|
|
79
|
+
"description": "Translate Current Segment",
|
|
80
|
+
"default": "Ctrl+T",
|
|
81
|
+
"action": "translate_current_segment"
|
|
82
|
+
},
|
|
83
|
+
"translate_batch": {
|
|
84
|
+
"category": "Translation",
|
|
85
|
+
"description": "Translate Multiple Segments",
|
|
86
|
+
"default": "Ctrl+Shift+T",
|
|
87
|
+
"action": "translate_batch"
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
# View Operations
|
|
91
|
+
"view_grid": {
|
|
92
|
+
"category": "View",
|
|
93
|
+
"description": "Switch to Grid View",
|
|
94
|
+
"default": "Ctrl+1",
|
|
95
|
+
"action": "switch_to_grid_view"
|
|
96
|
+
},
|
|
97
|
+
"view_list": {
|
|
98
|
+
"category": "View",
|
|
99
|
+
"description": "Switch to List View",
|
|
100
|
+
"default": "Ctrl+2",
|
|
101
|
+
"action": "switch_to_list_view"
|
|
102
|
+
},
|
|
103
|
+
"view_document": {
|
|
104
|
+
"category": "View",
|
|
105
|
+
"description": "Switch to Document View",
|
|
106
|
+
"default": "Ctrl+3",
|
|
107
|
+
"action": "switch_to_document_view"
|
|
108
|
+
},
|
|
109
|
+
"view_toggle_tags": {
|
|
110
|
+
"category": "View",
|
|
111
|
+
"description": "Toggle Tag View",
|
|
112
|
+
"default": "Ctrl+Alt+T",
|
|
113
|
+
"action": "toggle_tag_view"
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
# Grid Text Zoom
|
|
117
|
+
"grid_zoom_in": {
|
|
118
|
+
"category": "View",
|
|
119
|
+
"description": "Grid Zoom In",
|
|
120
|
+
"default": "Ctrl++",
|
|
121
|
+
"action": "increase_font_size"
|
|
122
|
+
},
|
|
123
|
+
"grid_zoom_out": {
|
|
124
|
+
"category": "View",
|
|
125
|
+
"description": "Grid Zoom Out",
|
|
126
|
+
"default": "Ctrl+-",
|
|
127
|
+
"action": "decrease_font_size"
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
# Results Pane Zoom
|
|
131
|
+
"results_zoom_in": {
|
|
132
|
+
"category": "View",
|
|
133
|
+
"description": "Results Pane Zoom In",
|
|
134
|
+
"default": "Ctrl+Shift+=",
|
|
135
|
+
"action": "results_pane_zoom_in"
|
|
136
|
+
},
|
|
137
|
+
"results_zoom_out": {
|
|
138
|
+
"category": "View",
|
|
139
|
+
"description": "Results Pane Zoom Out",
|
|
140
|
+
"default": "Ctrl+Shift+-",
|
|
141
|
+
"action": "results_pane_zoom_out"
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
# Resources & Tools
|
|
145
|
+
"tools_tm_manager_tab": {
|
|
146
|
+
"category": "Resources",
|
|
147
|
+
"description": "TM Manager (Launch in tab)",
|
|
148
|
+
"default": "Ctrl+M",
|
|
149
|
+
"action": "show_tm_manager_in_tab"
|
|
150
|
+
},
|
|
151
|
+
"tools_tm_manager_window": {
|
|
152
|
+
"category": "Resources",
|
|
153
|
+
"description": "TM Manager (Separate window)",
|
|
154
|
+
"default": "Ctrl+Shift+M",
|
|
155
|
+
"action": "show_tm_manager"
|
|
156
|
+
},
|
|
157
|
+
"tools_concordance_search": {
|
|
158
|
+
"category": "Resources",
|
|
159
|
+
"description": "Quick Concordance Search",
|
|
160
|
+
"default": "Ctrl+K",
|
|
161
|
+
"action": "show_concordance_search"
|
|
162
|
+
},
|
|
163
|
+
"tools_universal_lookup": {
|
|
164
|
+
"category": "Resources",
|
|
165
|
+
"description": "Universal Lookup",
|
|
166
|
+
"default": "Ctrl+Alt+L",
|
|
167
|
+
"action": "show_universal_lookup"
|
|
168
|
+
},
|
|
169
|
+
"tools_autofingers": {
|
|
170
|
+
"category": "Resources",
|
|
171
|
+
"description": "AutoFingers",
|
|
172
|
+
"default": "Ctrl+Shift+A",
|
|
173
|
+
"action": "show_autofingers"
|
|
174
|
+
},
|
|
175
|
+
"tools_force_refresh": {
|
|
176
|
+
"category": "Resources",
|
|
177
|
+
"description": "Force Refresh Matches (clear cache)",
|
|
178
|
+
"default": "F5",
|
|
179
|
+
"action": "force_refresh_matches"
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
# Special
|
|
183
|
+
"voice_dictate": {
|
|
184
|
+
"category": "Special",
|
|
185
|
+
"description": "Voice Dictation",
|
|
186
|
+
"default": "F9",
|
|
187
|
+
"action": "start_voice_dictation"
|
|
188
|
+
},
|
|
189
|
+
|
|
190
|
+
# Match Insertion (Direct)
|
|
191
|
+
"match_insert_1": {
|
|
192
|
+
"category": "Match Insertion",
|
|
193
|
+
"description": "Insert Match #1",
|
|
194
|
+
"default": "",
|
|
195
|
+
"action": "insert_match_1",
|
|
196
|
+
"context": "editor"
|
|
197
|
+
},
|
|
198
|
+
"match_insert_2": {
|
|
199
|
+
"category": "Match Insertion",
|
|
200
|
+
"description": "Insert Match #2",
|
|
201
|
+
"default": "",
|
|
202
|
+
"action": "insert_match_2",
|
|
203
|
+
"context": "editor"
|
|
204
|
+
},
|
|
205
|
+
"match_insert_3": {
|
|
206
|
+
"category": "Match Insertion",
|
|
207
|
+
"description": "Insert Match #3",
|
|
208
|
+
"default": "",
|
|
209
|
+
"action": "insert_match_3",
|
|
210
|
+
"context": "editor"
|
|
211
|
+
},
|
|
212
|
+
"match_insert_4": {
|
|
213
|
+
"category": "Match Insertion",
|
|
214
|
+
"description": "Insert Match #4",
|
|
215
|
+
"default": "",
|
|
216
|
+
"action": "insert_match_4",
|
|
217
|
+
"context": "editor"
|
|
218
|
+
},
|
|
219
|
+
"match_insert_5": {
|
|
220
|
+
"category": "Match Insertion",
|
|
221
|
+
"description": "Insert Match #5",
|
|
222
|
+
"default": "",
|
|
223
|
+
"action": "insert_match_5",
|
|
224
|
+
"context": "editor"
|
|
225
|
+
},
|
|
226
|
+
"match_insert_6": {
|
|
227
|
+
"category": "Match Insertion",
|
|
228
|
+
"description": "Insert Match #6",
|
|
229
|
+
"default": "",
|
|
230
|
+
"action": "insert_match_6",
|
|
231
|
+
"context": "editor"
|
|
232
|
+
},
|
|
233
|
+
"match_insert_7": {
|
|
234
|
+
"category": "Match Insertion",
|
|
235
|
+
"description": "Insert Match #7",
|
|
236
|
+
"default": "",
|
|
237
|
+
"action": "insert_match_7",
|
|
238
|
+
"context": "editor"
|
|
239
|
+
},
|
|
240
|
+
"match_insert_8": {
|
|
241
|
+
"category": "Match Insertion",
|
|
242
|
+
"description": "Insert Match #8",
|
|
243
|
+
"default": "",
|
|
244
|
+
"action": "insert_match_8",
|
|
245
|
+
"context": "editor"
|
|
246
|
+
},
|
|
247
|
+
"match_insert_9": {
|
|
248
|
+
"category": "Match Insertion",
|
|
249
|
+
"description": "Insert Match #9",
|
|
250
|
+
"default": "",
|
|
251
|
+
"action": "insert_match_9",
|
|
252
|
+
"context": "editor"
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
# Compare Panel Insertion
|
|
256
|
+
"compare_insert_alt0": {
|
|
257
|
+
"category": "Compare Panel",
|
|
258
|
+
"description": "Insert Compare Panel MT (Alt+0) / TM Target (Alt+0,0)",
|
|
259
|
+
"default": "Alt+0",
|
|
260
|
+
"action": "insert_compare_panel_alt0",
|
|
261
|
+
"context": "editor"
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
# Compare Panel Navigation
|
|
265
|
+
"compare_nav_mt_prev": {
|
|
266
|
+
"category": "Compare Panel",
|
|
267
|
+
"description": "Compare Panel: Previous MT result",
|
|
268
|
+
"default": "Ctrl+Alt+Left",
|
|
269
|
+
"action": "compare_panel_nav_mt_prev",
|
|
270
|
+
"context": "editor"
|
|
271
|
+
},
|
|
272
|
+
"compare_nav_mt_next": {
|
|
273
|
+
"category": "Compare Panel",
|
|
274
|
+
"description": "Compare Panel: Next MT result",
|
|
275
|
+
"default": "Ctrl+Alt+Right",
|
|
276
|
+
"action": "compare_panel_nav_mt_next",
|
|
277
|
+
"context": "editor"
|
|
278
|
+
},
|
|
279
|
+
"compare_nav_tm_prev": {
|
|
280
|
+
"category": "Compare Panel",
|
|
281
|
+
"description": "Compare Panel: Previous TM match",
|
|
282
|
+
"default": "Ctrl+Alt+Up",
|
|
283
|
+
"action": "compare_panel_nav_tm_prev",
|
|
284
|
+
"context": "editor"
|
|
285
|
+
},
|
|
286
|
+
"compare_nav_tm_next": {
|
|
287
|
+
"category": "Compare Panel",
|
|
288
|
+
"description": "Compare Panel: Next TM match",
|
|
289
|
+
"default": "Ctrl+Alt+Down",
|
|
290
|
+
"action": "compare_panel_nav_tm_next",
|
|
291
|
+
"context": "editor"
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
# TermView Insertion (Alt+0-9, double-tap for 00-99)
|
|
295
|
+
"termview_insert_0": {
|
|
296
|
+
"category": "TermView Insertion",
|
|
297
|
+
"description": "Insert TermView Term [0] (or [00] if double-tap)",
|
|
298
|
+
"default": "",
|
|
299
|
+
"action": "insert_termview_0",
|
|
300
|
+
"context": "editor"
|
|
301
|
+
},
|
|
302
|
+
"termview_insert_1": {
|
|
303
|
+
"category": "TermView Insertion",
|
|
304
|
+
"description": "Insert TermView Term [1] (or [11] if double-tap)",
|
|
305
|
+
"default": "Alt+1",
|
|
306
|
+
"action": "insert_termview_1",
|
|
307
|
+
"context": "editor"
|
|
308
|
+
},
|
|
309
|
+
"termview_insert_2": {
|
|
310
|
+
"category": "TermView Insertion",
|
|
311
|
+
"description": "Insert TermView Term [2] (or [22] if double-tap)",
|
|
312
|
+
"default": "Alt+2",
|
|
313
|
+
"action": "insert_termview_2",
|
|
314
|
+
"context": "editor"
|
|
315
|
+
},
|
|
316
|
+
"termview_insert_3": {
|
|
317
|
+
"category": "TermView Insertion",
|
|
318
|
+
"description": "Insert TermView Term [3] (or [33] if double-tap)",
|
|
319
|
+
"default": "Alt+3",
|
|
320
|
+
"action": "insert_termview_3",
|
|
321
|
+
"context": "editor"
|
|
322
|
+
},
|
|
323
|
+
"termview_insert_4": {
|
|
324
|
+
"category": "TermView Insertion",
|
|
325
|
+
"description": "Insert TermView Term [4] (or [44] if double-tap)",
|
|
326
|
+
"default": "Alt+4",
|
|
327
|
+
"action": "insert_termview_4",
|
|
328
|
+
"context": "editor"
|
|
329
|
+
},
|
|
330
|
+
"termview_insert_5": {
|
|
331
|
+
"category": "TermView Insertion",
|
|
332
|
+
"description": "Insert TermView Term [5] (or [55] if double-tap)",
|
|
333
|
+
"default": "Alt+5",
|
|
334
|
+
"action": "insert_termview_5",
|
|
335
|
+
"context": "editor"
|
|
336
|
+
},
|
|
337
|
+
"termview_insert_6": {
|
|
338
|
+
"category": "TermView Insertion",
|
|
339
|
+
"description": "Insert TermView Term [6] (or [66] if double-tap)",
|
|
340
|
+
"default": "Alt+6",
|
|
341
|
+
"action": "insert_termview_6",
|
|
342
|
+
"context": "editor"
|
|
343
|
+
},
|
|
344
|
+
"termview_insert_7": {
|
|
345
|
+
"category": "TermView Insertion",
|
|
346
|
+
"description": "Insert TermView Term [7] (or [77] if double-tap)",
|
|
347
|
+
"default": "Alt+7",
|
|
348
|
+
"action": "insert_termview_7",
|
|
349
|
+
"context": "editor"
|
|
350
|
+
},
|
|
351
|
+
"termview_insert_8": {
|
|
352
|
+
"category": "TermView Insertion",
|
|
353
|
+
"description": "Insert TermView Term [8] (or [88] if double-tap)",
|
|
354
|
+
"default": "Alt+8",
|
|
355
|
+
"action": "insert_termview_8",
|
|
356
|
+
"context": "editor"
|
|
357
|
+
},
|
|
358
|
+
"termview_insert_9": {
|
|
359
|
+
"category": "TermView Insertion",
|
|
360
|
+
"description": "Insert TermView Term [9] (or [99] if double-tap)",
|
|
361
|
+
"default": "Alt+9",
|
|
362
|
+
"action": "insert_termview_9",
|
|
363
|
+
"context": "editor"
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
# Match Navigation
|
|
367
|
+
"match_next": {
|
|
368
|
+
"category": "Match Navigation",
|
|
369
|
+
"description": "Next Match (in results panel)",
|
|
370
|
+
"default": "Down",
|
|
371
|
+
"action": "next_match",
|
|
372
|
+
"context": "match_panel"
|
|
373
|
+
},
|
|
374
|
+
"match_previous": {
|
|
375
|
+
"category": "Match Navigation",
|
|
376
|
+
"description": "Previous Match (in results panel)",
|
|
377
|
+
"default": "Up",
|
|
378
|
+
"action": "previous_match",
|
|
379
|
+
"context": "match_panel"
|
|
380
|
+
},
|
|
381
|
+
"match_cycle_next": {
|
|
382
|
+
"category": "Match Navigation",
|
|
383
|
+
"description": "Cycle to Next Match (from grid)",
|
|
384
|
+
"default": "Ctrl+Down",
|
|
385
|
+
"action": "select_next_match",
|
|
386
|
+
"context": "grid"
|
|
387
|
+
},
|
|
388
|
+
"match_cycle_previous": {
|
|
389
|
+
"category": "Match Navigation",
|
|
390
|
+
"description": "Cycle to Previous Match (from grid)",
|
|
391
|
+
"default": "Ctrl+Up",
|
|
392
|
+
"action": "select_previous_match",
|
|
393
|
+
"context": "grid"
|
|
394
|
+
},
|
|
395
|
+
"match_insert_selected": {
|
|
396
|
+
"category": "Match Navigation",
|
|
397
|
+
"description": "Insert Selected Match",
|
|
398
|
+
"default": "Space or Enter",
|
|
399
|
+
"action": "insert_selected_match",
|
|
400
|
+
"context": "match_panel"
|
|
401
|
+
},
|
|
402
|
+
"match_insert_selected_ctrl": {
|
|
403
|
+
"category": "Match Navigation",
|
|
404
|
+
"description": "Insert Selected Match (from grid)",
|
|
405
|
+
"default": "Ctrl+Space",
|
|
406
|
+
"action": "insert_selected_match",
|
|
407
|
+
"context": "grid"
|
|
408
|
+
},
|
|
409
|
+
|
|
410
|
+
# Grid Navigation
|
|
411
|
+
"segment_next": {
|
|
412
|
+
"category": "Grid Navigation",
|
|
413
|
+
"description": "Next Segment",
|
|
414
|
+
"default": "Alt+Down",
|
|
415
|
+
"action": "go_to_next_segment"
|
|
416
|
+
},
|
|
417
|
+
"segment_previous": {
|
|
418
|
+
"category": "Grid Navigation",
|
|
419
|
+
"description": "Previous Segment",
|
|
420
|
+
"default": "Alt+Up",
|
|
421
|
+
"action": "go_to_previous_segment"
|
|
422
|
+
},
|
|
423
|
+
"segment_go_to_top": {
|
|
424
|
+
"category": "Grid Navigation",
|
|
425
|
+
"description": "Go to First Segment",
|
|
426
|
+
"default": "Ctrl+Home",
|
|
427
|
+
"action": "go_to_first_segment"
|
|
428
|
+
},
|
|
429
|
+
"segment_go_to_bottom": {
|
|
430
|
+
"category": "Grid Navigation",
|
|
431
|
+
"description": "Go to Last Segment",
|
|
432
|
+
"default": "Ctrl+End",
|
|
433
|
+
"action": "go_to_last_segment"
|
|
434
|
+
},
|
|
435
|
+
"page_prev": {
|
|
436
|
+
"category": "Grid Navigation",
|
|
437
|
+
"description": "Previous Page (pagination)",
|
|
438
|
+
"default": "PgUp",
|
|
439
|
+
"action": "go_to_prev_page"
|
|
440
|
+
},
|
|
441
|
+
"page_next": {
|
|
442
|
+
"category": "Grid Navigation",
|
|
443
|
+
"description": "Next Page (pagination)",
|
|
444
|
+
"default": "PgDown",
|
|
445
|
+
"action": "go_to_next_page"
|
|
446
|
+
},
|
|
447
|
+
"select_range_up": {
|
|
448
|
+
"category": "Grid Navigation",
|
|
449
|
+
"description": "Select Range Upward (one page)",
|
|
450
|
+
"default": "Shift+PgUp",
|
|
451
|
+
"action": "select_range_page_up"
|
|
452
|
+
},
|
|
453
|
+
"select_range_down": {
|
|
454
|
+
"category": "Grid Navigation",
|
|
455
|
+
"description": "Select Range Downward (one page)",
|
|
456
|
+
"default": "Shift+PgDown",
|
|
457
|
+
"action": "select_range_page_down"
|
|
458
|
+
},
|
|
459
|
+
|
|
460
|
+
# Editor Operations
|
|
461
|
+
"editor_save_and_next": {
|
|
462
|
+
"category": "Editor",
|
|
463
|
+
"description": "Save & Next Segment",
|
|
464
|
+
"default": "Ctrl+Enter",
|
|
465
|
+
"action": "save_and_next",
|
|
466
|
+
"context": "editor"
|
|
467
|
+
},
|
|
468
|
+
"editor_confirm_selected": {
|
|
469
|
+
"category": "Editor",
|
|
470
|
+
"description": "Confirm All Selected Segments",
|
|
471
|
+
"default": "Ctrl+Shift+Enter",
|
|
472
|
+
"action": "confirm_selected_segments",
|
|
473
|
+
"context": "editor"
|
|
474
|
+
},
|
|
475
|
+
"editor_line_break": {
|
|
476
|
+
"category": "Editor",
|
|
477
|
+
"description": "Insert Line Break",
|
|
478
|
+
"default": "Ctrl+Enter",
|
|
479
|
+
"action": "insert_line_break",
|
|
480
|
+
"context": "editor_alt"
|
|
481
|
+
},
|
|
482
|
+
"editor_cycle_source_target": {
|
|
483
|
+
"category": "Editor",
|
|
484
|
+
"description": "Cycle between Source/Target cells",
|
|
485
|
+
"default": "Tab",
|
|
486
|
+
"action": "cycle_source_target",
|
|
487
|
+
"context": "grid_editor"
|
|
488
|
+
},
|
|
489
|
+
"editor_insert_tab": {
|
|
490
|
+
"category": "Editor",
|
|
491
|
+
"description": "Insert Tab character",
|
|
492
|
+
"default": "Ctrl+Tab",
|
|
493
|
+
"action": "insert_tab",
|
|
494
|
+
"context": "grid_editor"
|
|
495
|
+
},
|
|
496
|
+
"editor_add_to_termbase": {
|
|
497
|
+
"category": "Editor",
|
|
498
|
+
"description": "Add selected term pair to termbase (with dialog)",
|
|
499
|
+
"default": "Ctrl+E",
|
|
500
|
+
"action": "add_to_termbase",
|
|
501
|
+
"context": "grid_editor"
|
|
502
|
+
},
|
|
503
|
+
"editor_quick_add_to_termbase": {
|
|
504
|
+
"category": "Editor",
|
|
505
|
+
"description": "Quick add term pair to last-used termbase",
|
|
506
|
+
"default": "Alt+Left",
|
|
507
|
+
"action": "quick_add_to_termbase",
|
|
508
|
+
"context": "grid_editor"
|
|
509
|
+
},
|
|
510
|
+
"editor_quick_add_priority_1": {
|
|
511
|
+
"category": "Editor",
|
|
512
|
+
"description": "Quick add term pair with Priority 1",
|
|
513
|
+
"default": "Ctrl+Shift+1",
|
|
514
|
+
"action": "quick_add_term_priority_1",
|
|
515
|
+
"context": "grid_editor"
|
|
516
|
+
},
|
|
517
|
+
"editor_quick_add_priority_2": {
|
|
518
|
+
"category": "Editor",
|
|
519
|
+
"description": "Quick add term pair with Priority 2",
|
|
520
|
+
"default": "Ctrl+Shift+2",
|
|
521
|
+
"action": "quick_add_term_priority_2",
|
|
522
|
+
"context": "grid_editor"
|
|
523
|
+
},
|
|
524
|
+
"editor_add_to_non_translatables": {
|
|
525
|
+
"category": "Editor",
|
|
526
|
+
"description": "Add selected text to non-translatables list",
|
|
527
|
+
"default": "Ctrl+Alt+N",
|
|
528
|
+
"action": "add_to_non_translatables",
|
|
529
|
+
"context": "grid_editor"
|
|
530
|
+
},
|
|
531
|
+
"editor_insert_next_tag": {
|
|
532
|
+
"category": "Editor",
|
|
533
|
+
"description": "Insert next tag (memoQ/CafeTran) or wrap selection",
|
|
534
|
+
"default": "Ctrl+,",
|
|
535
|
+
"action": "insert_next_tag",
|
|
536
|
+
"context": "grid_editor"
|
|
537
|
+
},
|
|
538
|
+
"editor_copy_source_to_target": {
|
|
539
|
+
"category": "Editor",
|
|
540
|
+
"description": "Copy source text to target",
|
|
541
|
+
"default": "Ctrl+Shift+S",
|
|
542
|
+
"action": "copy_source_to_target",
|
|
543
|
+
"context": "grid_editor"
|
|
544
|
+
},
|
|
545
|
+
|
|
546
|
+
# Filter Operations
|
|
547
|
+
"filter_selected_text": {
|
|
548
|
+
"category": "Filter",
|
|
549
|
+
"description": "Filter on selected text / Clear filter (toggle)",
|
|
550
|
+
"default": "Ctrl+Shift+F",
|
|
551
|
+
"action": "filter_on_selected_text"
|
|
552
|
+
},
|
|
553
|
+
"clear_filter": {
|
|
554
|
+
"category": "Filter",
|
|
555
|
+
"description": "Clear filter (same as above - toggle behavior)",
|
|
556
|
+
"default": "Ctrl+Shift+F",
|
|
557
|
+
"action": "filter_on_selected_text"
|
|
558
|
+
},
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
def __init__(self, settings_file: Optional[Path] = None):
|
|
562
|
+
"""
|
|
563
|
+
Initialize ShortcutManager
|
|
564
|
+
|
|
565
|
+
Args:
|
|
566
|
+
settings_file: Path to JSON file for storing custom shortcuts
|
|
567
|
+
"""
|
|
568
|
+
self.settings_file = settings_file or Path("user_data/shortcuts.json")
|
|
569
|
+
self.custom_shortcuts = {}
|
|
570
|
+
self.disabled_shortcuts = set() # Set of disabled shortcut IDs
|
|
571
|
+
self.load_shortcuts()
|
|
572
|
+
|
|
573
|
+
def load_shortcuts(self):
|
|
574
|
+
"""Load custom shortcuts from file"""
|
|
575
|
+
if self.settings_file.exists():
|
|
576
|
+
try:
|
|
577
|
+
with open(self.settings_file, 'r', encoding='utf-8') as f:
|
|
578
|
+
data = json.load(f)
|
|
579
|
+
# Support both old format (dict of shortcuts) and new format (dict with shortcuts + disabled)
|
|
580
|
+
if isinstance(data, dict):
|
|
581
|
+
if "shortcuts" in data:
|
|
582
|
+
# New format: {"shortcuts": {...}, "disabled": [...]}
|
|
583
|
+
self.custom_shortcuts = data.get("shortcuts", {})
|
|
584
|
+
self.disabled_shortcuts = set(data.get("disabled", []))
|
|
585
|
+
else:
|
|
586
|
+
# Old format: just the shortcuts dict
|
|
587
|
+
self.custom_shortcuts = data
|
|
588
|
+
self.disabled_shortcuts = set()
|
|
589
|
+
else:
|
|
590
|
+
self.custom_shortcuts = {}
|
|
591
|
+
self.disabled_shortcuts = set()
|
|
592
|
+
except Exception as e:
|
|
593
|
+
print(f"Error loading shortcuts: {e}")
|
|
594
|
+
self.custom_shortcuts = {}
|
|
595
|
+
self.disabled_shortcuts = set()
|
|
596
|
+
|
|
597
|
+
def save_shortcuts(self):
|
|
598
|
+
"""Save custom shortcuts to file"""
|
|
599
|
+
try:
|
|
600
|
+
self.settings_file.parent.mkdir(parents=True, exist_ok=True)
|
|
601
|
+
# Save in new format that includes both shortcuts and disabled list
|
|
602
|
+
save_data = {
|
|
603
|
+
"shortcuts": self.custom_shortcuts,
|
|
604
|
+
"disabled": list(self.disabled_shortcuts)
|
|
605
|
+
}
|
|
606
|
+
with open(self.settings_file, 'w', encoding='utf-8') as f:
|
|
607
|
+
json.dump(save_data, f, indent=2)
|
|
608
|
+
except Exception as e:
|
|
609
|
+
print(f"Error saving shortcuts: {e}")
|
|
610
|
+
|
|
611
|
+
def get_shortcut(self, shortcut_id: str) -> str:
|
|
612
|
+
"""
|
|
613
|
+
Get the current shortcut for a given ID
|
|
614
|
+
|
|
615
|
+
Args:
|
|
616
|
+
shortcut_id: The shortcut identifier
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
The key sequence string (e.g., "Ctrl+T")
|
|
620
|
+
"""
|
|
621
|
+
if shortcut_id in self.custom_shortcuts:
|
|
622
|
+
return self.custom_shortcuts[shortcut_id]
|
|
623
|
+
|
|
624
|
+
if shortcut_id in self.DEFAULT_SHORTCUTS:
|
|
625
|
+
return self.DEFAULT_SHORTCUTS[shortcut_id]["default"]
|
|
626
|
+
|
|
627
|
+
return ""
|
|
628
|
+
|
|
629
|
+
def is_enabled(self, shortcut_id: str) -> bool:
|
|
630
|
+
"""
|
|
631
|
+
Check if a shortcut is enabled
|
|
632
|
+
|
|
633
|
+
Args:
|
|
634
|
+
shortcut_id: The shortcut identifier
|
|
635
|
+
|
|
636
|
+
Returns:
|
|
637
|
+
True if enabled (not in disabled set), False if disabled
|
|
638
|
+
"""
|
|
639
|
+
return shortcut_id not in self.disabled_shortcuts
|
|
640
|
+
|
|
641
|
+
def enable_shortcut(self, shortcut_id: str):
|
|
642
|
+
"""
|
|
643
|
+
Enable a previously disabled shortcut
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
shortcut_id: The shortcut identifier
|
|
647
|
+
"""
|
|
648
|
+
self.disabled_shortcuts.discard(shortcut_id)
|
|
649
|
+
|
|
650
|
+
def disable_shortcut(self, shortcut_id: str):
|
|
651
|
+
"""
|
|
652
|
+
Disable a shortcut
|
|
653
|
+
|
|
654
|
+
Args:
|
|
655
|
+
shortcut_id: The shortcut identifier
|
|
656
|
+
"""
|
|
657
|
+
self.disabled_shortcuts.add(shortcut_id)
|
|
658
|
+
|
|
659
|
+
def set_shortcut(self, shortcut_id: str, key_sequence: str):
|
|
660
|
+
"""
|
|
661
|
+
Set a custom shortcut
|
|
662
|
+
|
|
663
|
+
Args:
|
|
664
|
+
shortcut_id: The shortcut identifier
|
|
665
|
+
key_sequence: The new key sequence string
|
|
666
|
+
"""
|
|
667
|
+
if key_sequence:
|
|
668
|
+
self.custom_shortcuts[shortcut_id] = key_sequence
|
|
669
|
+
elif shortcut_id in self.custom_shortcuts:
|
|
670
|
+
del self.custom_shortcuts[shortcut_id]
|
|
671
|
+
|
|
672
|
+
def reset_shortcut(self, shortcut_id: str):
|
|
673
|
+
"""Reset a shortcut to its default value"""
|
|
674
|
+
if shortcut_id in self.custom_shortcuts:
|
|
675
|
+
del self.custom_shortcuts[shortcut_id]
|
|
676
|
+
|
|
677
|
+
def reset_all_shortcuts(self):
|
|
678
|
+
"""Reset all shortcuts to defaults"""
|
|
679
|
+
self.custom_shortcuts = {}
|
|
680
|
+
|
|
681
|
+
def get_all_shortcuts(self) -> Dict:
|
|
682
|
+
"""
|
|
683
|
+
Get all shortcuts with their current values
|
|
684
|
+
|
|
685
|
+
Returns:
|
|
686
|
+
Dictionary of all shortcuts with metadata
|
|
687
|
+
"""
|
|
688
|
+
result = {}
|
|
689
|
+
for shortcut_id, data in self.DEFAULT_SHORTCUTS.items():
|
|
690
|
+
result[shortcut_id] = {
|
|
691
|
+
**data,
|
|
692
|
+
"current": self.get_shortcut(shortcut_id),
|
|
693
|
+
"is_custom": shortcut_id in self.custom_shortcuts,
|
|
694
|
+
"is_enabled": self.is_enabled(shortcut_id)
|
|
695
|
+
}
|
|
696
|
+
return result
|
|
697
|
+
|
|
698
|
+
def get_shortcuts_by_category(self) -> Dict[str, List[Tuple[str, Dict]]]:
|
|
699
|
+
"""
|
|
700
|
+
Get shortcuts organized by category
|
|
701
|
+
|
|
702
|
+
Returns:
|
|
703
|
+
Dictionary with categories as keys, list of (id, data) tuples as values
|
|
704
|
+
"""
|
|
705
|
+
categories = {}
|
|
706
|
+
all_shortcuts = self.get_all_shortcuts()
|
|
707
|
+
|
|
708
|
+
for shortcut_id, data in all_shortcuts.items():
|
|
709
|
+
category = data["category"]
|
|
710
|
+
if category not in categories:
|
|
711
|
+
categories[category] = []
|
|
712
|
+
categories[category].append((shortcut_id, data))
|
|
713
|
+
|
|
714
|
+
return categories
|
|
715
|
+
|
|
716
|
+
def find_conflicts(self, shortcut_id: str, key_sequence: str) -> List[str]:
|
|
717
|
+
"""
|
|
718
|
+
Find conflicts with a proposed shortcut
|
|
719
|
+
|
|
720
|
+
Args:
|
|
721
|
+
shortcut_id: The shortcut being changed
|
|
722
|
+
key_sequence: The proposed new key sequence
|
|
723
|
+
|
|
724
|
+
Returns:
|
|
725
|
+
List of conflicting shortcut IDs
|
|
726
|
+
"""
|
|
727
|
+
conflicts = []
|
|
728
|
+
for other_id, data in self.get_all_shortcuts().items():
|
|
729
|
+
if other_id != shortcut_id and data["current"] == key_sequence:
|
|
730
|
+
# Check if they're in different contexts (context-specific shortcuts don't conflict)
|
|
731
|
+
this_context = self.DEFAULT_SHORTCUTS.get(shortcut_id, {}).get("context")
|
|
732
|
+
other_context = self.DEFAULT_SHORTCUTS.get(other_id, {}).get("context")
|
|
733
|
+
|
|
734
|
+
# Only conflict if same context or no context specified
|
|
735
|
+
if this_context == other_context or not this_context or not other_context:
|
|
736
|
+
conflicts.append(other_id)
|
|
737
|
+
|
|
738
|
+
return conflicts
|
|
739
|
+
|
|
740
|
+
def export_shortcuts(self, file_path: Path):
|
|
741
|
+
"""
|
|
742
|
+
Export shortcuts to a JSON file
|
|
743
|
+
|
|
744
|
+
Args:
|
|
745
|
+
file_path: Path to export file
|
|
746
|
+
"""
|
|
747
|
+
export_data = {
|
|
748
|
+
"version": "1.0",
|
|
749
|
+
"shortcuts": self.custom_shortcuts,
|
|
750
|
+
"disabled": list(self.disabled_shortcuts)
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
754
|
+
json.dump(export_data, f, indent=2)
|
|
755
|
+
|
|
756
|
+
def import_shortcuts(self, file_path: Path) -> bool:
|
|
757
|
+
"""
|
|
758
|
+
Import shortcuts from a JSON file
|
|
759
|
+
|
|
760
|
+
Args:
|
|
761
|
+
file_path: Path to import file
|
|
762
|
+
|
|
763
|
+
Returns:
|
|
764
|
+
True if successful, False otherwise
|
|
765
|
+
"""
|
|
766
|
+
try:
|
|
767
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
768
|
+
import_data = json.load(f)
|
|
769
|
+
|
|
770
|
+
if "shortcuts" in import_data:
|
|
771
|
+
self.custom_shortcuts = import_data["shortcuts"]
|
|
772
|
+
self.disabled_shortcuts = set(import_data.get("disabled", []))
|
|
773
|
+
return True
|
|
774
|
+
return False
|
|
775
|
+
except Exception as e:
|
|
776
|
+
print(f"Error importing shortcuts: {e}")
|
|
777
|
+
return False
|
|
778
|
+
|
|
779
|
+
def export_html_cheatsheet(self, file_path: Path):
|
|
780
|
+
"""
|
|
781
|
+
Export shortcuts as an HTML cheatsheet
|
|
782
|
+
|
|
783
|
+
Args:
|
|
784
|
+
file_path: Path to export HTML file
|
|
785
|
+
"""
|
|
786
|
+
categories = self.get_shortcuts_by_category()
|
|
787
|
+
|
|
788
|
+
html = """
|
|
789
|
+
<!DOCTYPE html>
|
|
790
|
+
<html>
|
|
791
|
+
<head>
|
|
792
|
+
<meta charset="UTF-8">
|
|
793
|
+
<title>Supervertaler - Keyboard Shortcuts</title>
|
|
794
|
+
<style>
|
|
795
|
+
body {
|
|
796
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
797
|
+
max-width: 1200px;
|
|
798
|
+
margin: 40px auto;
|
|
799
|
+
padding: 20px;
|
|
800
|
+
background-color: #f5f5f5;
|
|
801
|
+
}
|
|
802
|
+
h1 {
|
|
803
|
+
color: #2196F3;
|
|
804
|
+
text-align: center;
|
|
805
|
+
border-bottom: 3px solid #2196F3;
|
|
806
|
+
padding-bottom: 20px;
|
|
807
|
+
}
|
|
808
|
+
h2 {
|
|
809
|
+
color: #1976D2;
|
|
810
|
+
margin-top: 40px;
|
|
811
|
+
margin-bottom: 20px;
|
|
812
|
+
border-left: 5px solid #2196F3;
|
|
813
|
+
padding-left: 15px;
|
|
814
|
+
}
|
|
815
|
+
table {
|
|
816
|
+
width: 100%;
|
|
817
|
+
border-collapse: collapse;
|
|
818
|
+
background-color: white;
|
|
819
|
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
820
|
+
margin-bottom: 30px;
|
|
821
|
+
}
|
|
822
|
+
th {
|
|
823
|
+
background-color: #2196F3;
|
|
824
|
+
color: white;
|
|
825
|
+
padding: 12px;
|
|
826
|
+
text-align: left;
|
|
827
|
+
font-weight: 600;
|
|
828
|
+
}
|
|
829
|
+
td {
|
|
830
|
+
padding: 10px 12px;
|
|
831
|
+
border-bottom: 1px solid #e0e0e0;
|
|
832
|
+
}
|
|
833
|
+
tr:hover {
|
|
834
|
+
background-color: #f5f5f5;
|
|
835
|
+
}
|
|
836
|
+
.shortcut {
|
|
837
|
+
font-family: 'Courier New', monospace;
|
|
838
|
+
background-color: #e3f2fd;
|
|
839
|
+
padding: 4px 8px;
|
|
840
|
+
border-radius: 4px;
|
|
841
|
+
font-weight: 600;
|
|
842
|
+
color: #1976D2;
|
|
843
|
+
}
|
|
844
|
+
.custom {
|
|
845
|
+
color: #4CAF50;
|
|
846
|
+
font-weight: 600;
|
|
847
|
+
}
|
|
848
|
+
.footer {
|
|
849
|
+
text-align: center;
|
|
850
|
+
margin-top: 40px;
|
|
851
|
+
color: #666;
|
|
852
|
+
font-size: 0.9em;
|
|
853
|
+
}
|
|
854
|
+
@media print {
|
|
855
|
+
body {
|
|
856
|
+
background-color: white;
|
|
857
|
+
}
|
|
858
|
+
table {
|
|
859
|
+
box-shadow: none;
|
|
860
|
+
page-break-inside: avoid;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
</style>
|
|
864
|
+
</head>
|
|
865
|
+
<body>
|
|
866
|
+
<h1>🌐 Supervertaler - Keyboard Shortcuts</h1>
|
|
867
|
+
<div class="footer" style="text-align: center; margin-bottom: 30px;">
|
|
868
|
+
<p>The Ultimate Translation Workbench</p>
|
|
869
|
+
</div>
|
|
870
|
+
"""
|
|
871
|
+
|
|
872
|
+
# Add each category
|
|
873
|
+
for category in sorted(categories.keys()):
|
|
874
|
+
shortcuts = categories[category]
|
|
875
|
+
html += f" <h2>{category}</h2>\n"
|
|
876
|
+
html += " <table>\n"
|
|
877
|
+
html += " <tr><th>Action</th><th>Shortcut</th></tr>\n"
|
|
878
|
+
|
|
879
|
+
for shortcut_id, data in sorted(shortcuts, key=lambda x: x[1]["description"]):
|
|
880
|
+
description = data["description"]
|
|
881
|
+
current = data["current"]
|
|
882
|
+
is_custom = data["is_custom"]
|
|
883
|
+
|
|
884
|
+
custom_mark = " <span class='custom'>(Custom)</span>" if is_custom else ""
|
|
885
|
+
|
|
886
|
+
html += f" <tr>\n"
|
|
887
|
+
html += f" <td>{description}{custom_mark}</td>\n"
|
|
888
|
+
html += f" <td><span class='shortcut'>{current}</span></td>\n"
|
|
889
|
+
html += f" </tr>\n"
|
|
890
|
+
|
|
891
|
+
html += " </table>\n"
|
|
892
|
+
|
|
893
|
+
html += """
|
|
894
|
+
<div class="footer">
|
|
895
|
+
<p>Generated by Supervertaler Qt Edition</p>
|
|
896
|
+
<p>For more information, visit <a href="https://supervertaler.com">supervertaler.com</a></p>
|
|
897
|
+
</div>
|
|
898
|
+
</body>
|
|
899
|
+
</html>
|
|
900
|
+
"""
|
|
901
|
+
|
|
902
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
903
|
+
f.write(html)
|
|
904
|
+
|