supervertaler 1.9.198__py3-none-any.whl → 1.9.203__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 CHANGED
@@ -32,9 +32,9 @@ License: MIT
32
32
  """
33
33
 
34
34
  # Version Information.
35
- __version__ = "1.9.198"
35
+ __version__ = "1.9.203"
36
36
  __phase__ = "0.9"
37
- __release_date__ = "2026-02-02"
37
+ __release_date__ = "2026-02-03"
38
38
  __edition__ = "Qt"
39
39
 
40
40
  import sys
@@ -474,33 +474,6 @@ def strip_outer_wrapping_tags(text: str) -> tuple:
474
474
  return (inner_content, tag_name)
475
475
 
476
476
 
477
- def get_list_prefix_for_tag(tag_name: str, list_position: int = 1) -> str:
478
- """
479
- Get visual prefix for list items in WYSIWYG mode.
480
-
481
- Args:
482
- tag_name: The outer wrapping tag name (e.g., 'li-o', 'li-b', 'li')
483
- list_position: Position within the list (1-indexed) for ordered lists
484
-
485
- Returns:
486
- Visual prefix string: "1. ", "2. ", "• ", etc., or "" if not a list tag
487
- """
488
- if not tag_name:
489
- return ""
490
-
491
- tag_lower = tag_name.lower()
492
-
493
- # Ordered list items
494
- if tag_lower == 'li-o':
495
- return f"{list_position}. "
496
-
497
- # Unordered/bullet list items
498
- if tag_lower in ('li-b', 'li'):
499
- return "• "
500
-
501
- return ""
502
-
503
-
504
477
  def has_formatting_tags(text: str) -> bool:
505
478
  """
506
479
  Check if text contains any formatting tags.
@@ -8294,30 +8267,7 @@ class SupervertalerQt(QMainWindow):
8294
8267
  grid_font_family_menu.addAction(font_action)
8295
8268
 
8296
8269
  view_menu.addSeparator()
8297
-
8298
- # Translation Results Pane section
8299
- results_zoom_menu = view_menu.addMenu("📋 Translation &Results Pane")
8300
-
8301
- results_zoom_in_action = QAction("Results Zoom &In", self)
8302
- results_zoom_in_action.setShortcut("Ctrl+Shift+=")
8303
- results_zoom_in_action.triggered.connect(self.results_pane_zoom_in)
8304
- results_zoom_menu.addAction(results_zoom_in_action)
8305
-
8306
- results_zoom_out_action = QAction("Results Zoom &Out", self)
8307
- results_zoom_out_action.setShortcut("Ctrl+Shift+-")
8308
- results_zoom_out_action.triggered.connect(self.results_pane_zoom_out)
8309
- results_zoom_menu.addAction(results_zoom_out_action)
8310
-
8311
- results_zoom_reset_action = QAction("Results Zoom &Reset", self)
8312
- results_zoom_reset_action.triggered.connect(self.results_pane_zoom_reset)
8313
- results_zoom_menu.addAction(results_zoom_reset_action)
8314
-
8315
- results_zoom_menu.addSeparator()
8316
-
8317
- results_note = QAction("(Includes match list + compare boxes)", self)
8318
- results_note.setEnabled(False)
8319
- results_zoom_menu.addAction(results_note)
8320
-
8270
+
8321
8271
  # Match Panel zoom section
8322
8272
  match_panel_zoom_menu = view_menu.addMenu("🔍 &Match Panel")
8323
8273
 
@@ -17808,10 +17758,10 @@ class SupervertalerQt(QMainWindow):
17808
17758
  hide_wrapping_tags_check = CheckmarkCheckBox("Hide outer wrapping tags in grid (e.g. <li-o>...</li-o>)")
17809
17759
  hide_wrapping_tags_check.setChecked(font_settings.get('hide_outer_wrapping_tags', False))
17810
17760
  hide_wrapping_tags_check.setToolTip(
17811
- "When enabled, structural tags that wrap the entire segment (like <li-o>, <p>, <td>) are hidden in the grid.\n"
17812
- "The segment type is already shown in the Type column, so this reduces visual clutter.\n"
17813
- "Inner formatting tags like <b>bold</b> are still shown.\n"
17814
- "This affects the Source column display only - the Target column keeps tags for editing."
17761
+ "When enabled, structural tags that wrap the entire segment (like <li-o>, <p>, <td>) are hidden.\n"
17762
+ "Tags are automatically restored when saving. List items show visual prefixes (1. 2. or •).\n"
17763
+ "The segment type is shown in the Type column, so outer tags are redundant.\n"
17764
+ "Inner formatting tags like <b>bold</b> are still shown."
17815
17765
  )
17816
17766
  hide_wrapping_tags_layout.addWidget(hide_wrapping_tags_check)
17817
17767
  hide_wrapping_tags_layout.addStretch()
@@ -20432,8 +20382,9 @@ class SupervertalerQt(QMainWindow):
20432
20382
 
20433
20383
  # Add hide outer wrapping tags setting if provided
20434
20384
  if hide_wrapping_tags_check is not None:
20435
- general_settings['hide_outer_wrapping_tags'] = hide_wrapping_tags_check.isChecked()
20436
- self.hide_outer_wrapping_tags = hide_wrapping_tags_check.isChecked()
20385
+ hide_tags_value = hide_wrapping_tags_check.isChecked()
20386
+ general_settings['hide_outer_wrapping_tags'] = hide_tags_value
20387
+ self.hide_outer_wrapping_tags = hide_tags_value
20437
20388
 
20438
20389
  # Add focus border settings if provided
20439
20390
  if border_color_btn is not None:
@@ -21413,70 +21364,46 @@ class SupervertalerQt(QMainWindow):
21413
21364
 
21414
21365
  # Add left side to main horizontal splitter
21415
21366
  main_horizontal_splitter.addWidget(left_container)
21416
-
21417
- # Right side: Translation Results panel with Preview tab
21418
- from modules.translation_results_panel import TranslationResultsPanel
21419
-
21367
+
21420
21368
  # Create tabbed container for right panel
21421
21369
  right_tabs = QTabWidget()
21422
21370
  right_tabs.tabBar().setFocusPolicy(Qt.FocusPolicy.NoFocus)
21423
21371
  right_tabs.tabBar().setDrawBase(False)
21424
21372
  right_tabs.setStyleSheet("QTabBar::tab { outline: 0; } QTabBar::tab:focus { outline: none; } QTabBar::tab:selected { border-bottom: 1px solid #2196F3; background-color: rgba(33, 150, 243, 0.08); }")
21425
-
21426
- # Tab 1: Translation Results
21427
- self.translation_results_panel = TranslationResultsPanel(right_tabs, parent_app=self)
21428
-
21429
- # Connect signals for match selection/insertion
21430
- self.translation_results_panel.match_selected.connect(self.on_match_selected)
21431
- self.translation_results_panel.match_inserted.connect(self.on_match_inserted)
21432
-
21433
- # Connect notes editing to save segment notes
21434
- if hasattr(self.translation_results_panel, 'notes_edit') and self.translation_results_panel.notes_edit:
21435
- self.translation_results_panel.notes_edit.textChanged.connect(self._on_results_panel_notes_changed)
21436
-
21437
- # Register this panel so it receives updates when segments are selected
21373
+
21374
+ # NOTE: Translation Results panel is deprecated - MT/LLM is now only via QuickTrans (Ctrl+M)
21375
+ # Panel is no longer created to save resources. Set to None for compatibility checks.
21376
+ self.translation_results_panel = None
21438
21377
  if not hasattr(self, 'results_panels'):
21439
21378
  self.results_panels = []
21440
- self.results_panels.append(self.translation_results_panel)
21441
-
21379
+
21442
21380
  # Track tab indices for visibility-aware default selection
21443
21381
  tab_index = 0
21444
- results_tab_index = -1
21445
- compare_tab_index = -1
21446
21382
  preview_tab_index = -1
21447
-
21448
- # Tab 1: Translation Results (conditionally added)
21449
- if self.show_translation_results_pane:
21450
- right_tabs.addTab(self.translation_results_panel, "🔍 Translation Results")
21451
- results_tab_index = tab_index
21452
- tab_index += 1
21453
- else:
21454
- # Hide the panel if not added as tab (it still exists as child widget)
21455
- self.translation_results_panel.hide()
21456
-
21457
- # Tab 2: Match Panel (Termview + TM Source/Target) - shown first by default
21383
+
21384
+ # Tab 1: Match Panel (Termview + TM Source/Target) - primary TM display
21458
21385
  match_panel_widget = self._create_match_panel()
21459
21386
  self.match_panel_widget = match_panel_widget # Store reference for mode detection
21460
21387
  right_tabs.addTab(match_panel_widget, "🎯 Match Panel")
21461
21388
  match_panel_tab_index = tab_index
21462
21389
  tab_index += 1
21463
21390
 
21464
- # Tab 4: Document Preview (always added)
21391
+ # Tab 2: Document Preview
21465
21392
  preview_widget = self._create_preview_tab()
21466
21393
  right_tabs.addTab(preview_widget, "📄 Preview")
21467
21394
  preview_tab_index = tab_index
21468
21395
  self._preview_tab_index = preview_tab_index # Store for visibility checks
21469
21396
  tab_index += 1
21470
-
21471
- # Tab 5: Segment Note (moved from bottom panel)
21397
+
21398
+ # Tab 3: Segment Note
21472
21399
  right_tabs.addTab(self._notes_widget_for_right_panel, "📝 Segment note")
21473
21400
  tab_index += 1
21474
-
21475
- # Tab 6: Session Log (moved from bottom panel)
21401
+
21402
+ # Tab 4: Session Log
21476
21403
  right_tabs.addTab(self._session_log_widget_for_right_panel, "📋 Session Log")
21477
21404
  tab_index += 1
21478
-
21479
- # Tab 7: Scratchpad (private translator notes for the whole project)
21405
+
21406
+ # Tab 5: Scratchpad (private translator notes for the whole project)
21480
21407
  right_tabs.addTab(self._scratchpad_widget_for_right_panel, "📝 Scratchpad")
21481
21408
  tab_index += 1
21482
21409
 
@@ -21623,7 +21550,13 @@ class SupervertalerQt(QMainWindow):
21623
21550
  self.table.setRowHidden(row, not in_page)
21624
21551
  finally:
21625
21552
  self.table.setUpdatesEnabled(True)
21626
-
21553
+
21554
+ # Recalculate heights for visible rows to prevent layout corruption.
21555
+ # Call synchronously first, then schedule a deferred resize to catch any
21556
+ # layout issues that Qt processes asynchronously.
21557
+ self._resize_visible_rows()
21558
+ QTimer.singleShot(50, self._resize_visible_rows)
21559
+
21627
21560
  # Update pagination UI
21628
21561
  self._update_pagination_ui()
21629
21562
 
@@ -21915,7 +21848,10 @@ class SupervertalerQt(QMainWindow):
21915
21848
  header.setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch) # Target - stretch to fill space
21916
21849
  header.setSectionResizeMode(4, QHeaderView.ResizeMode.Interactive) # Status - allow resizing
21917
21850
  header.setStretchLastSection(False) # Don't auto-stretch last section (we use Stretch mode for Source/Target)
21918
-
21851
+
21852
+ # Recalculate row heights when columns are resized (text reflows to new width)
21853
+ header.sectionResized.connect(self._on_column_resized)
21854
+
21919
21855
  # Set initial column widths - give Source and Target equal space
21920
21856
  # ID column width will be auto-adjusted by _update_segment_column_width() after segments load
21921
21857
  self.table.setColumnWidth(0, 35) # ID - temporary, auto-adjusts to fit content
@@ -23797,6 +23733,9 @@ class SupervertalerQt(QMainWindow):
23797
23733
  - 'latest': Overwrites existing entries with same source (keeps only newest translation)
23798
23734
  - 'all': Keeps all translations with different targets (default SQLite behavior)
23799
23735
 
23736
+ If hide_outer_wrapping_tags is enabled, strips structural tags (like <li-o>, <p>)
23737
+ before saving to TM for better matching leverage.
23738
+
23800
23739
  Args:
23801
23740
  source: Source text
23802
23741
  target: Target text
@@ -23804,6 +23743,11 @@ class SupervertalerQt(QMainWindow):
23804
23743
  if not self.current_project:
23805
23744
  return
23806
23745
 
23746
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
23747
+ if self.hide_outer_wrapping_tags:
23748
+ source, _ = strip_outer_wrapping_tags(source)
23749
+ target, _ = strip_outer_wrapping_tags(target)
23750
+
23807
23751
  if not hasattr(self.current_project, 'source_lang') or not hasattr(self.current_project, 'target_lang'):
23808
23752
  return
23809
23753
 
@@ -29946,16 +29890,9 @@ class SupervertalerQt(QMainWindow):
29946
29890
  # Strip outer wrapping tags if setting is enabled (display only, data unchanged)
29947
29891
  source_for_display = segment.source
29948
29892
  stripped_source_tag = None
29949
- list_prefix = ""
29950
29893
  if self.hide_outer_wrapping_tags:
29951
29894
  stripped, stripped_source_tag = strip_outer_wrapping_tags(segment.source)
29952
29895
  source_for_display = stripped
29953
- # Add WYSIWYG list prefix (e.g., "1. " or "• ") for list items
29954
- if stripped_source_tag:
29955
- list_pos = list_numbers.get(row, 1)
29956
- list_prefix = get_list_prefix_for_tag(stripped_source_tag, list_pos)
29957
- if list_prefix:
29958
- source_for_display = list_prefix + source_for_display
29959
29896
  # Apply invisible character replacements for display only
29960
29897
  source_display_text = self.apply_invisible_replacements(source_for_display)
29961
29898
  source_editor = ReadOnlyGridTextEditor(source_display_text, self.table, row)
@@ -29979,26 +29916,19 @@ class SupervertalerQt(QMainWindow):
29979
29916
  # Strip outer wrapping tags if enabled (will be auto-restored when saving)
29980
29917
  target_for_display = segment.target
29981
29918
  stripped_target_tag = None
29982
- target_list_prefix = ""
29983
29919
  if self.hide_outer_wrapping_tags:
29984
29920
  stripped, stripped_target_tag = strip_outer_wrapping_tags(segment.target)
29985
29921
  target_for_display = stripped
29986
29922
  # Store stripped tag on segment for restore during save
29987
29923
  # Use source tag as reference (target should match source structure)
29988
29924
  segment._stripped_outer_tag = stripped_source_tag or stripped_target_tag
29989
- # Add WYSIWYG list prefix for display (same as source)
29990
- target_list_prefix = list_prefix # Reuse the prefix calculated for source
29991
29925
 
29992
29926
  # Apply invisible character replacements for display (will be reversed when saving)
29993
29927
  target_display_text = self.apply_invisible_replacements(target_for_display)
29994
- # Add list prefix for display (stored separately so we can strip it on save)
29995
- if target_list_prefix:
29996
- target_display_text = target_list_prefix + target_display_text
29997
29928
  target_editor = EditableGridTextEditor(target_display_text, self.table, row, self.table)
29998
29929
  target_editor.setFont(font)
29999
- # Store stripped tag and list prefix on editor for auto-restore
29930
+ # Store stripped tag on editor for auto-restore
30000
29931
  target_editor._stripped_outer_tag = stripped_source_tag or stripped_target_tag
30001
- target_editor._list_prefix = target_list_prefix
30002
29932
 
30003
29933
  # Connect text changes to update segment
30004
29934
  # Use a factory function to create a proper closure that captures the segment ID
@@ -30010,11 +29940,6 @@ class SupervertalerQt(QMainWindow):
30010
29940
  nonlocal debounce_timer
30011
29941
  new_text = editor_widget.toPlainText()
30012
29942
 
30013
- # Strip WYSIWYG list prefix if present (display-only, not saved)
30014
- list_prefix = getattr(editor_widget, '_list_prefix', '')
30015
- if list_prefix and new_text.startswith(list_prefix):
30016
- new_text = new_text[len(list_prefix):]
30017
-
30018
29943
  # Reverse invisible character replacements before saving
30019
29944
  new_text = self.reverse_invisible_replacements(new_text)
30020
29945
 
@@ -30155,10 +30080,15 @@ class SupervertalerQt(QMainWindow):
30155
30080
 
30156
30081
  # Update progress stats in status bar
30157
30082
  self.update_progress_stats()
30158
-
30083
+
30159
30084
  # Refresh document preview
30160
30085
  self.refresh_preview()
30161
30086
 
30087
+ # Deferred row resize: columns use Stretch mode, so their final widths
30088
+ # are only known after Qt processes the layout. Schedule a resize for
30089
+ # after all pending events are processed.
30090
+ QTimer.singleShot(0, self._resize_visible_rows)
30091
+
30162
30092
  # =========================================================================
30163
30093
  # COMPARE PANEL TAB
30164
30094
  # =========================================================================
@@ -31111,14 +31041,15 @@ class SupervertalerQt(QMainWindow):
31111
31041
  import re
31112
31042
  list_numbers = {} # {segment_id: list_number}
31113
31043
  list_counter = 0
31114
-
31044
+ prev_was_ordered_list = False
31045
+
31115
31046
  for seg in self.current_project.segments:
31116
31047
  source_text = seg.source.strip() if seg.source else ""
31117
-
31048
+
31118
31049
  # Check for list tags (new <li-o>, <li-b> and legacy <li>)
31119
31050
  has_li_ordered = '<li-o>' in source_text or ('<li>' in source_text and '<li-b>' not in source_text)
31120
31051
  has_li_bullet = '<li-b>' in source_text
31121
-
31052
+
31122
31053
  if has_li_ordered:
31123
31054
  # Check for explicit number in text
31124
31055
  num_match = re.match(r'^<li(?:-o)?>\s*(\d+)[.)\s]', source_text)
@@ -31126,8 +31057,15 @@ class SupervertalerQt(QMainWindow):
31126
31057
  list_numbers[seg.id] = int(num_match.group(1))
31127
31058
  list_counter = int(num_match.group(1))
31128
31059
  else:
31060
+ # Reset counter if starting a new list (gap since last ordered item)
31061
+ if not prev_was_ordered_list:
31062
+ list_counter = 0
31129
31063
  list_counter += 1
31130
31064
  list_numbers[seg.id] = list_counter
31065
+ prev_was_ordered_list = True
31066
+ else:
31067
+ # Not an ordered list item - mark gap for potential new list
31068
+ prev_was_ordered_list = False
31131
31069
 
31132
31070
  # Render all segments
31133
31071
  current_segment_id = self._get_current_segment_id()
@@ -31142,12 +31080,20 @@ class SupervertalerQt(QMainWindow):
31142
31080
  # Type field values: "para", "heading", "list_item", "table_cell", "Sub", "¶", etc.
31143
31081
  seg_type_lower = seg_type.lower() if seg_type else 'para'
31144
31082
 
31083
+ # Check if this is a list item (need source_text first)
31084
+ source_text = seg.source.strip() if seg.source else ""
31085
+
31145
31086
  # Check if this is a heading/subtitle
31146
- is_heading = ('Heading' in style or 'Title' in style or 'Subtitle' in style
31087
+ # Also detect bold-wrapped short text as section headings (e.g., <b>TECHNICAL FIELD</b>)
31088
+ is_heading = ('Heading' in style or 'Title' in style or 'Subtitle' in style
31147
31089
  or seg_type_lower in ('heading', 'sub', 'subtitle', 'title'))
31148
-
31149
- # Check if this is a list item
31150
- source_text = seg.source.strip() if seg.source else ""
31090
+
31091
+ # Detect bold section headings: <b>TEXT</b> where text is short and likely a heading
31092
+ if not is_heading and source_text.startswith('<b>') and source_text.endswith('</b>'):
31093
+ inner_text = source_text[3:-4].strip() # Remove <b> and </b>
31094
+ # Short text (under 80 chars) that's bold is likely a section heading
31095
+ if len(inner_text) < 80 and '<' not in inner_text:
31096
+ is_heading = True
31151
31097
  is_list_item = ('<li-o>' in source_text or '<li-b>' in source_text or
31152
31098
  '<li>' in source_text or seg_type_lower == 'list_item')
31153
31099
 
@@ -31166,9 +31112,15 @@ class SupervertalerQt(QMainWindow):
31166
31112
  prev_type = getattr(prev_seg, 'type', 'para') or 'para'
31167
31113
  prev_type_lower = prev_type.lower() if prev_type else 'para'
31168
31114
 
31169
- prev_is_heading = ('Heading' in prev_style or 'Title' in prev_style or
31170
- 'Subtitle' in prev_style or
31115
+ prev_is_heading = ('Heading' in prev_style or 'Title' in prev_style or
31116
+ 'Subtitle' in prev_style or
31171
31117
  prev_type_lower in ('heading', 'sub', 'subtitle', 'title'))
31118
+ # Also detect bold section headings in previous segment
31119
+ prev_source = prev_seg.source.strip() if prev_seg.source else ""
31120
+ if not prev_is_heading and prev_source.startswith('<b>') and prev_source.endswith('</b>'):
31121
+ prev_inner = prev_source[3:-4].strip()
31122
+ if len(prev_inner) < 80 and '<' not in prev_inner:
31123
+ prev_is_heading = True
31172
31124
  prev_is_paragraph = prev_type == '¶' or prev_type_lower == 'para'
31173
31125
  prev_is_list = prev_type_lower == 'list_item' or '<li' in (prev_seg.source or '')
31174
31126
 
@@ -31190,9 +31142,15 @@ class SupervertalerQt(QMainWindow):
31190
31142
  else:
31191
31143
  # Same paragraph, running text
31192
31144
  need_space = True
31193
- # 4. List items: single break (each on own line)
31145
+ # 4. List items: ordered list items (like claims) get paragraph spacing
31194
31146
  elif is_list_item or prev_is_list:
31195
- need_single_break = True
31147
+ # Ordered list items (<li-o>) get double breaks for visual separation
31148
+ is_ordered_list = '<li-o>' in source_text or ('<li>' in source_text and '<li-b>' not in source_text)
31149
+ prev_is_ordered = '<li-o>' in (prev_seg.source or '') or ('<li>' in (prev_seg.source or '') and '<li-b>' not in (prev_seg.source or ''))
31150
+ if is_ordered_list or prev_is_ordered:
31151
+ need_double_break = True # Paragraph-like spacing for numbered items
31152
+ else:
31153
+ need_single_break = True # Bullet lists stay compact
31196
31154
  # 5. Default: space (running text)
31197
31155
  else:
31198
31156
  need_space = True
@@ -31227,6 +31185,11 @@ class SupervertalerQt(QMainWindow):
31227
31185
  char_format.setFontPointSize(13)
31228
31186
  char_format.setFontWeight(QFont.Weight.Bold)
31229
31187
  char_format.setForeground(QColor('#1f4068'))
31188
+ elif is_heading:
31189
+ # Bold section headings detected from <b>TEXT</b> pattern
31190
+ char_format.setFontPointSize(12)
31191
+ char_format.setFontWeight(QFont.Weight.Bold)
31192
+ char_format.setForeground(QColor('#1a365d'))
31230
31193
  else:
31231
31194
  char_format.setFontPointSize(11)
31232
31195
  char_format.setForeground(QColor('#2d2d2d'))
@@ -31485,9 +31448,11 @@ class SupervertalerQt(QMainWindow):
31485
31448
  def _refresh_segment_status(self, segment: Segment):
31486
31449
  if not self.current_project:
31487
31450
  return
31451
+ updated_row = None
31488
31452
  for row, seg in enumerate(self.current_project.segments):
31489
31453
  if seg.id == segment.id:
31490
31454
  self._update_status_cell(row, seg)
31455
+ updated_row = row
31491
31456
  break
31492
31457
 
31493
31458
  # Update list view entry in place (if visible)
@@ -31509,7 +31474,10 @@ class SupervertalerQt(QMainWindow):
31509
31474
  status_tooltip += f"\nComment: {segment.notes.strip()}"
31510
31475
  item.setToolTip(2, status_tooltip)
31511
31476
  item.setBackground(2, QColor(status_def.color))
31512
- self._enforce_status_row_heights()
31477
+
31478
+ # Recalculate row height after status cell update to prevent layout corruption
31479
+ if updated_row is not None:
31480
+ self._auto_resize_single_row(updated_row)
31513
31481
 
31514
31482
  def _refresh_segment_status_by_id(self, segment_id: int):
31515
31483
  """Refresh the status display for a segment by its ID."""
@@ -31572,40 +31540,79 @@ class SupervertalerQt(QMainWindow):
31572
31540
  return
31573
31541
  if row < 0 or row >= self.table.rowCount():
31574
31542
  return
31575
-
31543
+
31544
+ # Minimum column width threshold - if columns are narrower than this,
31545
+ # layout isn't ready yet and we should skip resizing
31546
+ MIN_COL_WIDTH = 100
31547
+
31576
31548
  max_height = 1
31577
-
31549
+
31578
31550
  # Check source cell (column 2)
31579
31551
  source_widget = self.table.cellWidget(row, 2)
31580
31552
  if source_widget and isinstance(source_widget, ReadOnlyGridTextEditor):
31581
31553
  doc = source_widget.document()
31582
31554
  if doc:
31583
31555
  col_width = self.table.columnWidth(2) - width_reduction
31584
- if col_width > 0:
31556
+ if col_width >= MIN_COL_WIDTH:
31585
31557
  doc.setTextWidth(col_width)
31586
- size = doc.size()
31587
- if size.isValid():
31588
- height = int(size.height())
31589
- max_height = max(max_height, height)
31590
-
31558
+ # Use documentLayout().documentSize() to force fresh calculation
31559
+ layout = doc.documentLayout()
31560
+ if layout:
31561
+ size = layout.documentSize()
31562
+ if size.isValid():
31563
+ height = int(size.height())
31564
+ max_height = max(max_height, height)
31565
+
31591
31566
  # Check target cell (column 3)
31592
31567
  target_widget = self.table.cellWidget(row, 3)
31593
31568
  if target_widget and isinstance(target_widget, EditableGridTextEditor):
31594
31569
  doc = target_widget.document()
31595
31570
  if doc:
31596
31571
  col_width = self.table.columnWidth(3) - width_reduction
31597
- if col_width > 0:
31572
+ if col_width >= MIN_COL_WIDTH:
31598
31573
  doc.setTextWidth(col_width)
31599
- size = doc.size()
31600
- if size.isValid():
31601
- height = int(size.height())
31602
- max_height = max(max_height, height)
31574
+ # Use documentLayout().documentSize() to force fresh calculation
31575
+ layout = doc.documentLayout()
31576
+ if layout:
31577
+ size = layout.documentSize()
31578
+ if size.isValid():
31579
+ height = int(size.height())
31580
+ max_height = max(max_height, height)
31603
31581
 
31604
31582
  # Set row height with minimal padding
31605
31583
  # Minimum 32px to accommodate status icons (16px) + match text + padding without any cutoff
31606
31584
  compact_height = max(max_height + 2, 32)
31607
31585
  self.table.setRowHeight(row, compact_height)
31608
-
31586
+
31587
+ def _resize_visible_rows(self):
31588
+ """Resize only visible (non-hidden) rows for efficiency after pagination/filter changes."""
31589
+ if not hasattr(self, 'table') or not self.table:
31590
+ return
31591
+ row_count = self.table.rowCount()
31592
+ for row in range(row_count):
31593
+ if not self.table.isRowHidden(row):
31594
+ self._auto_resize_single_row(row)
31595
+
31596
+ def _on_column_resized(self, logical_index: int, old_size: int, new_size: int):
31597
+ """Handle column resize - recalculate row heights for text reflow.
31598
+
31599
+ Only reacts to Source (2) or Target (3) column changes since those
31600
+ contain wrapped text. Uses debouncing to avoid excessive recalculations
31601
+ during continuous dragging.
31602
+ """
31603
+ # Only care about Source or Target columns (they contain wrapped text)
31604
+ if logical_index not in (2, 3):
31605
+ return
31606
+
31607
+ # Debounce: cancel previous timer and start a new one
31608
+ if hasattr(self, '_column_resize_timer') and self._column_resize_timer is not None:
31609
+ self._column_resize_timer.stop()
31610
+
31611
+ self._column_resize_timer = QTimer()
31612
+ self._column_resize_timer.setSingleShot(True)
31613
+ self._column_resize_timer.timeout.connect(self._resize_visible_rows)
31614
+ self._column_resize_timer.start(150) # 150ms debounce
31615
+
31609
31616
  def apply_font_to_grid(self):
31610
31617
  """Apply selected font to all grid cells"""
31611
31618
  font = QFont(self.default_font_family, self.default_font_size)
@@ -34885,12 +34892,20 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
34885
34892
  self.log("💡 Tip: Go to Resources tab to activate TMs and glossaries for this project")
34886
34893
 
34887
34894
  def search_and_display_tm_matches(self, source_text: str):
34888
- """Search TM and Termbases and display matches with visual diff for fuzzy matches"""
34895
+ """Search TM and Termbases and display matches with visual diff for fuzzy matches.
34896
+
34897
+ If hide_outer_wrapping_tags is enabled, strips structural tags (like <li-o>, <p>)
34898
+ from the query before searching for better TM matching.
34899
+ """
34889
34900
  self.log(f"🚨 search_and_display_tm_matches called with source_text: '{source_text[:50]}...'")
34890
34901
  if not source_text or not source_text.strip():
34891
34902
  if hasattr(self, 'tm_display'):
34892
34903
  self.tm_display.clear()
34893
34904
  return
34905
+
34906
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
34907
+ if self.hide_outer_wrapping_tags:
34908
+ source_text, _ = strip_outer_wrapping_tags(source_text)
34894
34909
 
34895
34910
  # Initialize TM if not already done
34896
34911
  if not self.tm_database and self.current_project:
@@ -34967,14 +34982,18 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
34967
34982
  # Update grid (using cell widget)
34968
34983
  target_widget = self.table.cellWidget(current_row, 3)
34969
34984
  if target_widget and isinstance(target_widget, EditableGridTextEditor):
34970
- target_widget.setPlainText(segment.target)
34971
-
34985
+ # Strip outer wrapping tags if setting is enabled
34986
+ display_text = segment.target
34987
+ if self.hide_outer_wrapping_tags:
34988
+ display_text, _ = strip_outer_wrapping_tags(display_text)
34989
+ target_widget.setPlainText(display_text)
34990
+
34972
34991
  # Update status column
34973
34992
  status_item = self.table.item(current_row, 1)
34974
34993
  if status_item:
34975
34994
  status_item.setText("Translated")
34976
34995
  status_item.setBackground(QColor("#d1fae5")) # Light green for translated
34977
-
34996
+
34978
34997
  # Update project modified status (progress is handled by status bar)
34979
34998
  self.log(f"✨ Auto-propagated 100% TM match for segment #{current_row + 1}")
34980
34999
 
@@ -36032,7 +36051,11 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
36032
36051
  target_widget = self.table.cellWidget(row, 3)
36033
36052
  if target_widget and hasattr(target_widget, 'setPlainText'):
36034
36053
  target_widget.blockSignals(True)
36035
- target_widget.setPlainText(segment.target)
36054
+ # Strip outer wrapping tags if setting is enabled
36055
+ display_text = segment.target
36056
+ if self.hide_outer_wrapping_tags:
36057
+ display_text, _ = strip_outer_wrapping_tags(display_text)
36058
+ target_widget.setPlainText(display_text)
36036
36059
  target_widget.blockSignals(False)
36037
36060
  self.table.viewport().update()
36038
36061
 
@@ -36481,7 +36504,11 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
36481
36504
  cell_widget = self.table.cellWidget(row, col)
36482
36505
  if cell_widget and hasattr(cell_widget, 'setPlainText'):
36483
36506
  cell_widget.blockSignals(True)
36484
- cell_widget.setPlainText(new_text)
36507
+ # Strip outer wrapping tags if setting is enabled
36508
+ display_text = new_text
36509
+ if self.hide_outer_wrapping_tags:
36510
+ display_text, _ = strip_outer_wrapping_tags(display_text)
36511
+ cell_widget.setPlainText(display_text)
36485
36512
  cell_widget.blockSignals(False)
36486
36513
 
36487
36514
  self.project_modified = True
@@ -37422,10 +37449,10 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
37422
37449
  # Clear filtering flag to re-enable auto-center
37423
37450
  self.filtering_active = False
37424
37451
 
37425
- # Re-apply pagination after clearing filters
37452
+ # Re-apply pagination after clearing filters (also resizes visible rows)
37426
37453
  if hasattr(self, '_apply_pagination_to_grid'):
37427
37454
  self._apply_pagination_to_grid()
37428
-
37455
+
37429
37456
  # Restore selection to the previously selected segment
37430
37457
  if selected_segment_id is not None:
37431
37458
  for row, segment in enumerate(self.current_project.segments):
@@ -38693,7 +38720,12 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
38693
38720
  break
38694
38721
 
38695
38722
  def _on_results_panel_notes_changed(self):
38696
- """Handle notes change in Translation Results panel - saves to current segment"""
38723
+ """Handle notes change in Translation Results panel - saves to current segment.
38724
+ NOTE: This function is deprecated - Translation Results panel has been removed.
38725
+ """
38726
+ # Translation Results panel is deprecated - this should never be called
38727
+ if not self.translation_results_panel:
38728
+ return
38697
38729
  if not self.current_project:
38698
38730
  return
38699
38731
 
@@ -39571,13 +39603,19 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
39571
39603
  if target_widget and isinstance(target_widget, QTextEdit):
39572
39604
  from PyQt6.QtGui import QTextCursor
39573
39605
 
39606
+ # Strip outer wrapping tags for display if setting is enabled
39607
+ display_text = new_text
39608
+ if self.hide_outer_wrapping_tags:
39609
+ display_text, _ = strip_outer_wrapping_tags(display_text)
39610
+
39574
39611
  cursor = target_widget.textCursor()
39575
39612
  cursor.beginEditBlock()
39576
39613
  cursor.select(QTextCursor.SelectionType.Document)
39577
- cursor.insertText(new_text)
39614
+ cursor.insertText(display_text)
39578
39615
  cursor.endEditBlock()
39579
39616
 
39580
- segment.target = target_widget.toPlainText()
39617
+ # Store full text (with tags) in segment, but use displayed text if tags are hidden
39618
+ segment.target = new_text # Keep full text with tags
39581
39619
  target_widget.setFocus()
39582
39620
  target_widget.moveCursor(QTextCursor.MoveOperation.End)
39583
39621
 
@@ -39589,7 +39627,11 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
39589
39627
  # Fallback: no editor widget, update data and (if possible) update cell
39590
39628
  segment.target = new_text
39591
39629
  if target_widget and hasattr(target_widget, 'setPlainText'):
39592
- target_widget.setPlainText(new_text)
39630
+ # Strip outer wrapping tags if setting is enabled
39631
+ display_text = new_text
39632
+ if self.hide_outer_wrapping_tags:
39633
+ display_text, _ = strip_outer_wrapping_tags(display_text)
39634
+ target_widget.setPlainText(display_text)
39593
39635
  label = f" ({source_label})" if source_label else ""
39594
39636
  self.log(f"✓ Replaced target text in segment {segment_id}{label}")
39595
39637
  self._play_sound_effect('match_inserted')
@@ -40552,24 +40594,37 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
40552
40594
  """Refresh all visible cells to reflect current tag view mode"""
40553
40595
  if not hasattr(self, 'table') or not self.current_project:
40554
40596
  return
40555
-
40597
+
40556
40598
  # Get current visible rows
40557
40599
  for row in range(self.table.rowCount()):
40558
40600
  # Get segment for this row
40559
40601
  if row >= len(self.current_project.segments):
40560
40602
  continue
40561
-
40603
+
40562
40604
  segment = self.current_project.segments[row]
40563
-
40605
+
40606
+ # Apply tag stripping if enabled
40607
+ source_for_display = segment.source
40608
+ target_for_display = segment.target
40609
+
40610
+ if self.hide_outer_wrapping_tags:
40611
+ # Strip outer wrapping tags from source
40612
+ stripped_source, _ = strip_outer_wrapping_tags(segment.source)
40613
+ source_for_display = stripped_source
40614
+
40615
+ # Strip outer wrapping tags from target
40616
+ stripped_target, _ = strip_outer_wrapping_tags(segment.target)
40617
+ target_for_display = stripped_target
40618
+
40564
40619
  # Update source cell (column 2)
40565
40620
  source_widget = self.table.cellWidget(row, 2)
40566
40621
  if source_widget and hasattr(source_widget, 'update_display_mode'):
40567
- source_widget.update_display_mode(segment.source, self.show_tags)
40568
-
40622
+ source_widget.update_display_mode(source_for_display, self.show_tags)
40623
+
40569
40624
  # Update target cell (column 3)
40570
40625
  target_widget = self.table.cellWidget(row, 3)
40571
40626
  if target_widget and hasattr(target_widget, 'update_display_mode'):
40572
- target_widget.update_display_mode(segment.target, self.show_tags)
40627
+ target_widget.update_display_mode(target_for_display, self.show_tags)
40573
40628
 
40574
40629
  def update_tab_segment_editor(self, segment_id: int, source_text: str, target_text: str,
40575
40630
  status: str = "untranslated", notes: str = ""):
@@ -42091,15 +42146,20 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
42091
42146
  tm_ids = self.tm_metadata_mgr.get_active_tm_ids(project_id)
42092
42147
 
42093
42148
  try:
42149
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
42150
+ search_source = segment.source
42151
+ if self.hide_outer_wrapping_tags:
42152
+ search_source, _ = strip_outer_wrapping_tags(search_source)
42153
+
42094
42154
  if check_tm_exact_only:
42095
42155
  # Use exact match only (faster - O(1) hash lookup)
42096
- exact_match = self.tm_database.get_exact_match(segment.source, tm_ids=tm_ids)
42156
+ exact_match = self.tm_database.get_exact_match(search_source, tm_ids=tm_ids)
42097
42157
  if exact_match:
42098
42158
  tm_match = exact_match.get('target_text', '')
42099
42159
  self.log(f"✓ Found 100% TM match (exact) for segment #{segment.id}")
42100
42160
  else:
42101
42161
  # Use fuzzy search (includes 100% matches)
42102
- matches = self.tm_database.search_all(segment.source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
42162
+ matches = self.tm_database.search_all(search_source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
42103
42163
  if matches and matches[0].get('match_pct', 0) == 100:
42104
42164
  tm_match = matches[0].get('target', '')
42105
42165
  self.log(f"✓ Found 100% TM match for segment #{segment.id}")
@@ -43199,10 +43259,15 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43199
43259
 
43200
43260
  try:
43201
43261
  match = None
43202
-
43262
+
43263
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
43264
+ search_source = segment.source
43265
+ if self.hide_outer_wrapping_tags:
43266
+ search_source, _ = strip_outer_wrapping_tags(search_source)
43267
+
43203
43268
  if tm_exact_only:
43204
43269
  # Exact match only - use hash lookup (fast)
43205
- match = self.tm_database.get_exact_match(segment.source, tm_ids=tm_ids)
43270
+ match = self.tm_database.get_exact_match(search_source, tm_ids=tm_ids)
43206
43271
  print(f"DEBUG get_exact_match returned: type={type(match)}, value={match}")
43207
43272
  if match and isinstance(match, dict):
43208
43273
  segment.target = match.get('target_text', '')
@@ -43214,7 +43279,7 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43214
43279
  else:
43215
43280
  # Fuzzy matching enabled - get best match ≥75%
43216
43281
  matches = self.tm_database.search_all(
43217
- segment.source,
43282
+ search_source,
43218
43283
  tm_ids=tm_ids,
43219
43284
  enabled_only=False,
43220
43285
  max_matches=1
@@ -43236,7 +43301,11 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43236
43301
  if segment.target:
43237
43302
  target_widget = self.table.cellWidget(row_index, 3)
43238
43303
  if target_widget and isinstance(target_widget, EditableGridTextEditor):
43239
- target_widget.setPlainText(segment.target)
43304
+ # Strip outer wrapping tags if setting is enabled
43305
+ display_text = segment.target
43306
+ if self.hide_outer_wrapping_tags:
43307
+ display_text, _ = strip_outer_wrapping_tags(display_text)
43308
+ target_widget.setPlainText(display_text)
43240
43309
  self.update_status_icon(row_index, segment.status)
43241
43310
  QApplication.processEvents()
43242
43311
 
@@ -43305,11 +43374,15 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43305
43374
  if success and current <= len(segments_needing_translation):
43306
43375
  row_index, segment = segments_needing_translation[current - 1]
43307
43376
  if row_index < self.table.rowCount():
43377
+ # Strip outer wrapping tags if setting is enabled
43378
+ display_text = segment.target
43379
+ if self.hide_outer_wrapping_tags:
43380
+ display_text, _ = strip_outer_wrapping_tags(display_text)
43308
43381
  target_widget = self.table.cellWidget(row_index, 3)
43309
43382
  if target_widget and isinstance(target_widget, EditableGridTextEditor):
43310
- target_widget.setPlainText(segment.target)
43383
+ target_widget.setPlainText(display_text)
43311
43384
  else:
43312
- self.table.setItem(row_index, 3, QTableWidgetItem(segment.target))
43385
+ self.table.setItem(row_index, 3, QTableWidgetItem(display_text))
43313
43386
  self.update_status_icon(row_index, segment.status)
43314
43387
 
43315
43388
  def handle_translation_complete(final_success_count, final_error_count):
@@ -43477,9 +43550,14 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43477
43550
  # Check each segment against TM
43478
43551
  for row_index, segment in segments_to_translate:
43479
43552
  try:
43553
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
43554
+ search_source = segment.source
43555
+ if self.hide_outer_wrapping_tags:
43556
+ search_source, _ = strip_outer_wrapping_tags(search_source)
43557
+
43480
43558
  if check_tm_exact_only:
43481
43559
  # Use exact match only (faster - O(1) hash lookup)
43482
- exact_match = self.tm_database.get_exact_match(segment.source, tm_ids=tm_ids)
43560
+ exact_match = self.tm_database.get_exact_match(search_source, tm_ids=tm_ids)
43483
43561
  if exact_match:
43484
43562
  # Found 100% exact match - auto-insert it
43485
43563
  tm_match = exact_match.get('target_text', '')
@@ -43503,7 +43581,7 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43503
43581
  segments_needing_translation.append((row_index, segment))
43504
43582
  else:
43505
43583
  # Use fuzzy search (includes 100% matches)
43506
- matches = self.tm_database.search_all(segment.source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
43584
+ matches = self.tm_database.search_all(search_source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
43507
43585
  if matches and matches[0].get('match_pct', 0) == 100:
43508
43586
  # Found 100% match - auto-insert it
43509
43587
  tm_match = matches[0].get('target', '')
@@ -43582,8 +43660,13 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
43582
43660
  # Translate each segment from TM
43583
43661
  for row_index, segment in segments_needing_translation:
43584
43662
  try:
43663
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
43664
+ search_source = segment.source
43665
+ if self.hide_outer_wrapping_tags:
43666
+ search_source, _ = strip_outer_wrapping_tags(search_source)
43667
+
43585
43668
  # Search TM for best match
43586
- matches = self.tm_database.search_all(segment.source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
43669
+ matches = self.tm_database.search_all(search_source, tm_ids=tm_ids, enabled_only=False, max_matches=1)
43587
43670
 
43588
43671
  if matches and len(matches) > 0:
43589
43672
  match = matches[0]
@@ -45389,8 +45472,12 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
45389
45472
  if tm_ids is not None and isinstance(tm_ids, list) and len(tm_ids) == 0:
45390
45473
  all_tm_matches = []
45391
45474
  else:
45475
+ # Strip outer structural tags if setting is enabled (for cleaner TM matching)
45476
+ search_source = segment.source
45477
+ if self.hide_outer_wrapping_tags:
45478
+ search_source, _ = strip_outer_wrapping_tags(search_source)
45392
45479
  # Search using TMDatabase (includes bidirectional + base language matching)
45393
- all_tm_matches = self.tm_database.search_all(segment.source, tm_ids=tm_ids, enabled_only=False, max_matches=10)
45480
+ all_tm_matches = self.tm_database.search_all(search_source, tm_ids=tm_ids, enabled_only=False, max_matches=10)
45394
45481
 
45395
45482
  # Single consolidated log message for TM search results
45396
45483
  if all_tm_matches:
@@ -45576,9 +45663,19 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
45576
45663
  self.log(f"⚠ Error auto-inserting TM match: {e}")
45577
45664
 
45578
45665
  def _add_mt_and_llm_matches_progressive(self, segment, source_lang, target_lang, source_lang_code, target_lang_code):
45579
- """Add MT and LLM matches progressively - show each as it completes"""
45666
+ """DEPRECATED: Translation Results panel has been removed.
45667
+
45668
+ MT/LLM translations are now only available via QuickTrans (Ctrl+M).
45669
+ This function is kept as a stub for backwards compatibility.
45670
+ """
45671
+ pass # Translation Results panel removed - use QuickTrans (Ctrl+M) for MT/LLM
45672
+
45673
+ def _REMOVED_add_mt_and_llm_matches_progressive(self, segment, source_lang, target_lang, source_lang_code, target_lang_code):
45674
+ """REMOVED - kept for reference only, will be deleted in future cleanup."""
45675
+ return # Dead code below - keeping temporarily for reference
45676
+
45580
45677
  from modules.translation_results_panel import TranslationMatch
45581
-
45678
+
45582
45679
  # MT matches (usually fast ~0.5s each)
45583
45680
  if self.enable_mt_matching:
45584
45681
  api_keys = self.load_api_keys()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervertaler
3
- Version: 1.9.198
3
+ Version: 1.9.203
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,4 +1,4 @@
1
- Supervertaler.py,sha256=YY7nUEoaCqP0SZucFNKDqBuGhJDOgcUNb6lPbf9xsvo,2390297
1
+ Supervertaler.py,sha256=Mgq5ZnZJxaQ-_aSzVZoVQiVYz_kEaxeVq1nfq-6TkNE,2396397
2
2
  modules/__init__.py,sha256=G58XleS-EJ2sX4Kehm-3N2m618_W2Es0Kg8CW_eBG7g,327
3
3
  modules/ai_actions.py,sha256=i5MJcM-7Y6CAvKUwxmxrVHeoZAVtAP7aRDdWM5KLkO0,33877
4
4
  modules/ai_attachment_manager.py,sha256=juZlrW3UPkIkcnj0SREgOQkQROLf0fcu3ShZcKXMxsI,11361
@@ -80,9 +80,9 @@ modules/unified_prompt_manager_qt.py,sha256=y7xAIM9X7f1afXGE1tOcAc5EY7BKFy53Rgqi
80
80
  modules/voice_commands.py,sha256=iBb-gjWxRMLhFH7-InSRjYJz1EIDBNA2Pog8V7TtJaY,38516
81
81
  modules/voice_dictation.py,sha256=QmitXfkG-vRt5hIQATjphHdhXfqmwhzcQcbXB6aRzIg,16386
82
82
  modules/voice_dictation_lite.py,sha256=jorY0BmWE-8VczbtGrWwt1zbnOctMoSlWOsQrcufBcc,9423
83
- supervertaler-1.9.198.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
84
- supervertaler-1.9.198.dist-info/METADATA,sha256=XD0vrT3puNdRtUEj8oHeAnOkSJ7CohlYNWQo5_VkM8M,5725
85
- supervertaler-1.9.198.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
86
- supervertaler-1.9.198.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
87
- supervertaler-1.9.198.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
88
- supervertaler-1.9.198.dist-info/RECORD,,
83
+ supervertaler-1.9.203.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
84
+ supervertaler-1.9.203.dist-info/METADATA,sha256=Az4lNNikNxVVE-gTtXSSNrTM1F_aG4x1HhqjRtnbq0E,5725
85
+ supervertaler-1.9.203.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
86
+ supervertaler-1.9.203.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
87
+ supervertaler-1.9.203.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
88
+ supervertaler-1.9.203.dist-info/RECORD,,