supervertaler 1.9.185__py3-none-any.whl → 1.9.187__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 CHANGED
@@ -32,7 +32,7 @@ License: MIT
32
32
  """
33
33
 
34
34
  # Version Information.
35
- __version__ = "1.9.185"
35
+ __version__ = "1.9.187"
36
36
  __phase__ = "0.9"
37
37
  __release_date__ = "2026-02-01"
38
38
  __edition__ = "Qt"
@@ -20348,7 +20348,68 @@ class SupervertalerQt(QMainWindow):
20348
20348
  advanced_filter_btn.clicked.connect(self.show_advanced_filters_dialog)
20349
20349
  advanced_filter_btn.setMaximumWidth(160)
20350
20350
  advanced_filter_btn.setStyleSheet("background-color: #2196F3; color: white; font-weight: bold;")
20351
-
20351
+
20352
+ # Sort dropdown button (similar to memoQ)
20353
+ sort_btn = QPushButton("⇅ Sort")
20354
+ sort_btn.setMaximumWidth(100)
20355
+ sort_btn.setStyleSheet("background-color: #FF9800; color: white; font-weight: bold;")
20356
+ sort_menu = QMenu(sort_btn)
20357
+
20358
+ # Initialize sort state if not exists
20359
+ if not hasattr(self, 'current_sort'):
20360
+ self.current_sort = None # None = document order
20361
+
20362
+ # Sort by source text
20363
+ sort_menu.addAction("📝 Source A → Z", lambda: self.apply_sort('source_asc'))
20364
+ sort_menu.addAction("📝 Source Z → A", lambda: self.apply_sort('source_desc'))
20365
+
20366
+ sort_menu.addSeparator()
20367
+
20368
+ # Sort by target text
20369
+ sort_menu.addAction("📄 Target A → Z", lambda: self.apply_sort('target_asc'))
20370
+ sort_menu.addAction("📄 Target Z → A", lambda: self.apply_sort('target_desc'))
20371
+
20372
+ sort_menu.addSeparator()
20373
+
20374
+ # Sort by text length
20375
+ sort_menu.addAction("📏 Source (longer first)", lambda: self.apply_sort('source_length_desc'))
20376
+ sort_menu.addAction("📏 Source (shorter first)", lambda: self.apply_sort('source_length_asc'))
20377
+ sort_menu.addAction("📏 Target (longer first)", lambda: self.apply_sort('target_length_desc'))
20378
+ sort_menu.addAction("📏 Target (shorter first)", lambda: self.apply_sort('target_length_asc'))
20379
+
20380
+ sort_menu.addSeparator()
20381
+
20382
+ # Sort by match rate
20383
+ sort_menu.addAction("🎯 Match Rate (higher first)", lambda: self.apply_sort('match_desc'))
20384
+ sort_menu.addAction("🎯 Match Rate (lower first)", lambda: self.apply_sort('match_asc'))
20385
+
20386
+ sort_menu.addSeparator()
20387
+
20388
+ # Sort by frequency
20389
+ sort_menu.addAction("📊 Source Frequency (higher first)", lambda: self.apply_sort('source_freq_desc'))
20390
+ sort_menu.addAction("📊 Source Frequency (lower first)", lambda: self.apply_sort('source_freq_asc'))
20391
+ sort_menu.addAction("📊 Target Frequency (higher first)", lambda: self.apply_sort('target_freq_desc'))
20392
+ sort_menu.addAction("📊 Target Frequency (lower first)", lambda: self.apply_sort('target_freq_asc'))
20393
+
20394
+ sort_menu.addSeparator()
20395
+
20396
+ # Sort by last changed
20397
+ sort_menu.addAction("🕒 Last Changed (newest first)", lambda: self.apply_sort('modified_desc'))
20398
+ sort_menu.addAction("🕒 Last Changed (oldest first)", lambda: self.apply_sort('modified_asc'))
20399
+
20400
+ sort_menu.addSeparator()
20401
+
20402
+ # Sort by row status
20403
+ sort_menu.addAction("🚦 Row Status", lambda: self.apply_sort('status'))
20404
+
20405
+ sort_menu.addSeparator()
20406
+
20407
+ # Reset to document order
20408
+ sort_menu.addAction("↩️ Document Order (default)", lambda: self.apply_sort(None))
20409
+
20410
+ sort_btn.setMenu(sort_menu)
20411
+ sort_btn.setToolTip("Sort segments by various criteria")
20412
+
20352
20413
  # File filter dropdown (for multi-file projects)
20353
20414
  self.file_filter_combo = QComboBox()
20354
20415
  self.file_filter_combo.setMinimumWidth(150)
@@ -20442,6 +20503,7 @@ class SupervertalerQt(QMainWindow):
20442
20503
  filter_layout.addWidget(clear_filters_btn)
20443
20504
  filter_layout.addWidget(quick_filter_btn)
20444
20505
  filter_layout.addWidget(advanced_filter_btn)
20506
+ filter_layout.addWidget(sort_btn) # Sort dropdown
20445
20507
  filter_layout.addWidget(self.file_filter_combo) # File filter for multi-file projects
20446
20508
  filter_layout.addWidget(show_invisibles_btn_home)
20447
20509
  filter_layout.addWidget(self.spellcheck_btn)
@@ -20565,30 +20627,80 @@ class SupervertalerQt(QMainWindow):
20565
20627
  tab_seg_info.setStyleSheet("font-weight: bold;")
20566
20628
  toolbar_layout.addWidget(tab_seg_info)
20567
20629
 
20568
- # Tag View toggle button
20569
- tag_view_btn = QPushButton("🏷️ Tags OFF")
20570
- tag_view_btn.setCheckable(True)
20571
- tag_view_btn.setChecked(False) # Default: WYSIWYG mode (tags hidden)
20572
- tag_view_btn.setStyleSheet("""
20630
+ # View mode segmented control (WYSIWYG / Tags)
20631
+ from PyQt6.QtWidgets import QButtonGroup
20632
+
20633
+ view_mode_container = QWidget()
20634
+ view_mode_layout = QHBoxLayout(view_mode_container)
20635
+ view_mode_layout.setContentsMargins(0, 0, 0, 0)
20636
+ view_mode_layout.setSpacing(0)
20637
+
20638
+ # Create button group to ensure only one is checked
20639
+ view_mode_group = QButtonGroup(self)
20640
+ view_mode_group.setExclusive(True)
20641
+
20642
+ # WYSIWYG button (left)
20643
+ wysiwyg_btn = QPushButton("WYSIWYG")
20644
+ wysiwyg_btn.setCheckable(True)
20645
+ wysiwyg_btn.setChecked(False)
20646
+ wysiwyg_btn.setToolTip("WYSIWYG View (Ctrl+Alt+T)\nShows formatted text without raw tags")
20647
+ wysiwyg_btn.setStyleSheet("""
20573
20648
  QPushButton {
20574
20649
  background-color: #757575;
20575
20650
  color: white;
20576
20651
  font-weight: bold;
20577
- padding: 4px 8px;
20578
- border-radius: 3px;
20652
+ padding: 4px 12px;
20653
+ border: none;
20654
+ border-top-left-radius: 3px;
20655
+ border-bottom-left-radius: 3px;
20579
20656
  }
20580
20657
  QPushButton:checked {
20581
20658
  background-color: #9C27B0;
20582
20659
  }
20660
+ QPushButton:hover:!checked {
20661
+ background-color: #858585;
20662
+ }
20583
20663
  """)
20584
- tag_view_btn.setToolTip("Toggle Tag View (Ctrl+Alt+T)\n\nTags OFF: Shows formatted text (WYSIWYG)\nTags ON: Shows raw tags like <b>bold</b>")
20585
- tag_view_btn.clicked.connect(lambda checked: self.toggle_tag_view(checked, tag_view_btn))
20586
- toolbar_layout.addWidget(tag_view_btn)
20587
- self.tag_view_btn = tag_view_btn # Store reference
20664
+ wysiwyg_btn.clicked.connect(lambda: self.toggle_tag_view(False, None))
20665
+ view_mode_group.addButton(wysiwyg_btn, 0)
20666
+ view_mode_layout.addWidget(wysiwyg_btn)
20667
+
20668
+ # Tags button (right)
20669
+ tags_btn = QPushButton("Tags")
20670
+ tags_btn.setCheckable(True)
20671
+ tags_btn.setChecked(True) # Default: Tags mode
20672
+ tags_btn.setToolTip("Tag View (Ctrl+Alt+T)\nShows raw tags like <b>bold</b>")
20673
+ tags_btn.setStyleSheet("""
20674
+ QPushButton {
20675
+ background-color: #757575;
20676
+ color: white;
20677
+ font-weight: bold;
20678
+ padding: 4px 12px;
20679
+ border: none;
20680
+ border-top-right-radius: 3px;
20681
+ border-bottom-right-radius: 3px;
20682
+ }
20683
+ QPushButton:checked {
20684
+ background-color: #9C27B0;
20685
+ }
20686
+ QPushButton:hover:!checked {
20687
+ background-color: #858585;
20688
+ }
20689
+ """)
20690
+ tags_btn.clicked.connect(lambda: self.toggle_tag_view(True, None))
20691
+ view_mode_group.addButton(tags_btn, 1)
20692
+ view_mode_layout.addWidget(tags_btn)
20693
+
20694
+ toolbar_layout.addWidget(view_mode_container)
20695
+
20696
+ # Store references for keyboard shortcut and programmatic access
20697
+ self.wysiwyg_btn = wysiwyg_btn
20698
+ self.tags_btn = tags_btn
20699
+ self.view_mode_group = view_mode_group
20588
20700
 
20589
20701
  # Initialize tag view state
20590
20702
  if not hasattr(self, 'show_tags'):
20591
- self.show_tags = False
20703
+ self.show_tags = True # Default: show tags
20592
20704
 
20593
20705
  # Status selector
20594
20706
  from modules.statuses import get_status, STATUSES
@@ -37566,7 +37678,116 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
37566
37678
  self.table.setUpdatesEnabled(True)
37567
37679
 
37568
37680
  self.log(f"🔍 Advanced filters: showing {visible_count} of {len(self.current_project.segments)} segments")
37569
-
37681
+
37682
+ def apply_sort(self, sort_type: str = None):
37683
+ """Sort segments by various criteria (similar to memoQ)"""
37684
+ if not self.current_project or not hasattr(self, 'table') or self.table is None:
37685
+ return
37686
+
37687
+ if not self.current_project.segments:
37688
+ return
37689
+
37690
+ # Store original document order if not already stored
37691
+ if not hasattr(self, '_original_segment_order'):
37692
+ self._original_segment_order = self.current_project.segments.copy()
37693
+
37694
+ # Update current sort state
37695
+ self.current_sort = sort_type
37696
+
37697
+ # If sort_type is None, restore document order
37698
+ if sort_type is None:
37699
+ self.current_project.segments = self._original_segment_order.copy()
37700
+ self.load_segments_to_grid()
37701
+ self.log("↩️ Restored document order")
37702
+ return
37703
+
37704
+ # Helper function to get text without tags for more accurate sorting
37705
+ def strip_tags(text: str) -> str:
37706
+ """Remove HTML/XML tags from text for sorting"""
37707
+ import re
37708
+ return re.sub(r'<[^>]+>', '', text).strip()
37709
+
37710
+ # Calculate frequency maps if needed
37711
+ frequency_cache = {}
37712
+ if 'freq' in sort_type:
37713
+ from collections import Counter
37714
+ if 'source' in sort_type:
37715
+ counter = Counter(strip_tags(seg.source).lower() for seg in self.current_project.segments)
37716
+ frequency_cache = {strip_tags(seg.source).lower(): counter[strip_tags(seg.source).lower()]
37717
+ for seg in self.current_project.segments}
37718
+ else: # target frequency
37719
+ counter = Counter(strip_tags(seg.target).lower() for seg in self.current_project.segments if seg.target)
37720
+ frequency_cache = {strip_tags(seg.target).lower(): counter[strip_tags(seg.target).lower()]
37721
+ for seg in self.current_project.segments if seg.target}
37722
+
37723
+ # Sort based on selected criterion
37724
+ try:
37725
+ if sort_type == 'source_asc':
37726
+ self.current_project.segments.sort(key=lambda s: strip_tags(s.source).lower())
37727
+ sort_name = "Source A → Z"
37728
+ elif sort_type == 'source_desc':
37729
+ self.current_project.segments.sort(key=lambda s: strip_tags(s.source).lower(), reverse=True)
37730
+ sort_name = "Source Z → A"
37731
+ elif sort_type == 'target_asc':
37732
+ self.current_project.segments.sort(key=lambda s: strip_tags(s.target).lower() if s.target else "")
37733
+ sort_name = "Target A → Z"
37734
+ elif sort_type == 'target_desc':
37735
+ self.current_project.segments.sort(key=lambda s: strip_tags(s.target).lower() if s.target else "", reverse=True)
37736
+ sort_name = "Target Z → A"
37737
+ elif sort_type == 'source_length_asc':
37738
+ self.current_project.segments.sort(key=lambda s: len(strip_tags(s.source)))
37739
+ sort_name = "Source (shorter first)"
37740
+ elif sort_type == 'source_length_desc':
37741
+ self.current_project.segments.sort(key=lambda s: len(strip_tags(s.source)), reverse=True)
37742
+ sort_name = "Source (longer first)"
37743
+ elif sort_type == 'target_length_asc':
37744
+ self.current_project.segments.sort(key=lambda s: len(strip_tags(s.target)) if s.target else 0)
37745
+ sort_name = "Target (shorter first)"
37746
+ elif sort_type == 'target_length_desc':
37747
+ self.current_project.segments.sort(key=lambda s: len(strip_tags(s.target)) if s.target else 0, reverse=True)
37748
+ sort_name = "Target (longer first)"
37749
+ elif sort_type == 'match_asc':
37750
+ self.current_project.segments.sort(key=lambda s: getattr(s, 'match_percent', 0) or 0)
37751
+ sort_name = "Match Rate (lower first)"
37752
+ elif sort_type == 'match_desc':
37753
+ self.current_project.segments.sort(key=lambda s: getattr(s, 'match_percent', 0) or 0, reverse=True)
37754
+ sort_name = "Match Rate (higher first)"
37755
+ elif sort_type == 'source_freq_asc':
37756
+ self.current_project.segments.sort(key=lambda s: frequency_cache.get(strip_tags(s.source).lower(), 0))
37757
+ sort_name = "Source Frequency (lower first)"
37758
+ elif sort_type == 'source_freq_desc':
37759
+ self.current_project.segments.sort(key=lambda s: frequency_cache.get(strip_tags(s.source).lower(), 0), reverse=True)
37760
+ sort_name = "Source Frequency (higher first)"
37761
+ elif sort_type == 'target_freq_asc':
37762
+ self.current_project.segments.sort(key=lambda s: frequency_cache.get(strip_tags(s.target).lower(), 0) if s.target else 0)
37763
+ sort_name = "Target Frequency (lower first)"
37764
+ elif sort_type == 'target_freq_desc':
37765
+ self.current_project.segments.sort(key=lambda s: frequency_cache.get(strip_tags(s.target).lower(), 0) if s.target else 0, reverse=True)
37766
+ sort_name = "Target Frequency (higher first)"
37767
+ elif sort_type == 'modified_asc':
37768
+ self.current_project.segments.sort(key=lambda s: s.modified_at if s.modified_at else "")
37769
+ sort_name = "Last Changed (oldest first)"
37770
+ elif sort_type == 'modified_desc':
37771
+ self.current_project.segments.sort(key=lambda s: s.modified_at if s.modified_at else "", reverse=True)
37772
+ sort_name = "Last Changed (newest first)"
37773
+ elif sort_type == 'status':
37774
+ # Sort by status in a logical order: not_started, draft, translated, confirmed
37775
+ status_order = {'not_started': 0, 'draft': 1, 'translated': 2, 'confirmed': 3}
37776
+ self.current_project.segments.sort(key=lambda s: status_order.get(s.status, 99))
37777
+ sort_name = "Row Status"
37778
+ else:
37779
+ self.log(f"⚠️ Unknown sort type: {sort_type}")
37780
+ return
37781
+
37782
+ # Reload grid to reflect new order
37783
+ self.load_segments_to_grid()
37784
+ self.log(f"⇅ Sorted by: {sort_name}")
37785
+
37786
+ except Exception as e:
37787
+ self.log(f"❌ Error sorting segments: {e}")
37788
+ import traceback
37789
+ traceback.print_exc()
37790
+
37570
37791
  # ========================================================================
37571
37792
  # TABBED SEGMENT EDITOR METHODS (for Grid view)
37572
37793
  # ========================================================================
@@ -39560,32 +39781,30 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
39560
39781
 
39561
39782
  def _toggle_tag_view_via_shortcut(self):
39562
39783
  """Toggle tag view using keyboard shortcut (Ctrl+Alt+T)"""
39563
- if hasattr(self, 'tag_view_btn'):
39564
- # Toggle the button state (which triggers toggle_tag_view)
39565
- new_state = not self.tag_view_btn.isChecked()
39566
- self.tag_view_btn.setChecked(new_state)
39567
- self.toggle_tag_view(new_state, self.tag_view_btn)
39784
+ if hasattr(self, 'wysiwyg_btn') and hasattr(self, 'tags_btn'):
39785
+ # Toggle between the two modes
39786
+ new_state = not self.show_tags
39787
+ self.toggle_tag_view(new_state, None)
39568
39788
 
39569
39789
  def _enable_tag_view_after_import(self):
39570
39790
  """Auto-enable Tag View after importing a document with formatting tags"""
39571
- if hasattr(self, 'tag_view_btn'):
39572
- self.tag_view_btn.setChecked(True)
39573
- self.toggle_tag_view(True, self.tag_view_btn)
39791
+ if hasattr(self, 'tags_btn'):
39792
+ self.toggle_tag_view(True, None)
39574
39793
  self.log("🏷️ Tag View auto-enabled (formatting tags detected in import)")
39575
39794
 
39576
39795
  def toggle_tag_view(self, checked: bool, button: QPushButton = None):
39577
39796
  """Toggle between Tag View (showing raw tags) and WYSIWYG View (formatted display)"""
39578
39797
  self.show_tags = checked
39579
-
39580
- # Update button text
39581
- if button:
39798
+
39799
+ # Update segmented control buttons if they exist
39800
+ if hasattr(self, 'wysiwyg_btn') and hasattr(self, 'tags_btn'):
39582
39801
  if checked:
39583
- button.setText("🏷️ Tags ON")
39802
+ self.tags_btn.setChecked(True)
39584
39803
  else:
39585
- button.setText("🏷️ Tags OFF")
39586
-
39804
+ self.wysiwyg_btn.setChecked(True)
39805
+
39587
39806
  self.log(f"{'🏷️ Tag View ENABLED - showing raw tags' if checked else '✨ WYSIWYG View ENABLED - showing formatted text'}")
39588
-
39807
+
39589
39808
  # Refresh the grid to update display
39590
39809
  if hasattr(self, 'table') and self.current_project:
39591
39810
  self._refresh_grid_display_mode()
@@ -40958,45 +41177,12 @@ OUTPUT ONLY THE SEGMENT MARKERS. DO NOT ADD EXPLANATIONS BEFORE OR AFTER."""
40958
41177
  event.accept()
40959
41178
 
40960
41179
  def _cleanup_web_views(self):
40961
- """Clean up WebEngine views to prevent 'Release of profile requested' warning"""
40962
- try:
40963
- # Close any SuperBrowser tabs
40964
- if hasattr(self, 'superbrowser_tabs'):
40965
- for tab in self.superbrowser_tabs.values():
40966
- try:
40967
- if hasattr(tab, 'web_view'):
40968
- # Stop any loading/rendering
40969
- tab.web_view.stop()
40970
- # Clear page to release resources
40971
- tab.web_view.setPage(None)
40972
- tab.web_view.setUrl(QUrl('about:blank'))
40973
- tab.web_view.deleteLater()
40974
- except:
40975
- pass
40976
-
40977
- # Close Superlookup web views (from Web Resources tab)
40978
- if hasattr(self, 'web_views'):
40979
- for resource_id, web_view in list(self.web_views.items()):
40980
- try:
40981
- web_view.stop()
40982
- web_view.setPage(None)
40983
- web_view.setUrl(QUrl('about:blank'))
40984
- web_view.deleteLater()
40985
- except:
40986
- pass
40987
- self.web_views.clear()
40988
-
40989
- # Process events multiple times to ensure cleanup completes
40990
- from PyQt6.QtWidgets import QApplication
40991
- from PyQt6.QtCore import QUrl
40992
- for _ in range(3):
40993
- QApplication.processEvents()
40994
-
40995
- # Small delay to allow Qt to finish cleanup
40996
- import time
40997
- time.sleep(0.1)
40998
- except:
40999
- pass
41180
+ """Clean up WebEngine views - DISABLED to prevent crash"""
41181
+ # WebEngine cleanup has been disabled because it was causing Python crashes
41182
+ # on program exit. Qt will handle WebEngine cleanup automatically, though
41183
+ # you may see a "Release of profile requested" warning which is harmless.
41184
+ print("[WebEngine Cleanup] Skipping manual cleanup - letting Qt handle it")
41185
+ pass
41000
41186
 
41001
41187
  def _close_detached_log_windows(self):
41002
41188
  """Close all detached log windows when main window closes"""
modules/superbrowser.py CHANGED
@@ -160,6 +160,20 @@ class ChatColumn(QWidget):
160
160
  """Update URL bar when page changes"""
161
161
  self.url_input.setText(url.toString())
162
162
 
163
+ def cleanup(self):
164
+ """Clean up web engine resources before deletion"""
165
+ try:
166
+ from PyQt6.QtCore import QUrl
167
+ if hasattr(self, 'web_view'):
168
+ self.web_view.stop()
169
+ self.web_view.setPage(None)
170
+ self.web_view.setUrl(QUrl('about:blank'))
171
+ self.web_view.deleteLater()
172
+ if hasattr(self, 'profile'):
173
+ self.profile.deleteLater()
174
+ except:
175
+ pass
176
+
163
177
 
164
178
  class SuperbrowserWidget(QWidget):
165
179
  """
@@ -304,6 +318,14 @@ class SuperbrowserWidget(QWidget):
304
318
  self.claude_column.go_home()
305
319
  self.gemini_column.go_home()
306
320
 
321
+ def cleanup(self):
322
+ """Clean up all web engine resources before widget deletion"""
323
+ try:
324
+ for column in self.chat_columns:
325
+ column.cleanup()
326
+ except:
327
+ pass
328
+
307
329
 
308
330
  # ============================================================================
309
331
  # STANDALONE USAGE
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervertaler
3
- Version: 1.9.185
3
+ Version: 1.9.187
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=Lttb-7tBPZbYfBYDOay1P97sT_0Ea7cySgbmRNWiWhU,2342035
1
+ Supervertaler.py,sha256=yjoU32F4RBdhk9YDkX_nDgdi43NcOj5pqCiAFNwP_Kc,2351549
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
@@ -49,7 +49,7 @@ modules/spellcheck_manager.py,sha256=jwduHJ66pOKv1MtzSAltxpP8LPgz11FvF6j8h7BiRZY
49
49
  modules/statuses.py,sha256=t6TCA9pNZHDw3SbKTxT73uKezJhwWk9gFLr0NOgEufs,6911
50
50
  modules/style_guide_manager.py,sha256=QBvbygF2E-cgRuwJPWmIatwQl37voU1FErYnycv8Sac,10809
51
51
  modules/superbench_ui.py,sha256=O8pSb-R8Mul1Qz9-8gbBrFR1j7Z8b8_G0wSTSLSCf2U,55563
52
- modules/superbrowser.py,sha256=FAEaYTMiklXizYm3iPt83kp254bCGrFHRsGHduedKYI,12759
52
+ modules/superbrowser.py,sha256=jZw7jNOJyZdLTOVcbAdALH1MYiP43qi_4qGzNWxJ2Hs,13481
53
53
  modules/supercleaner.py,sha256=uRJAEh03Eu4Qtujrf_jxuIyPBbcxKAZzryhV9Chi9ro,22939
54
54
  modules/supercleaner_ui.py,sha256=sVTnYxlX9R20eWs52BKCeQ15iFVFOIQEl29L72lup1c,18812
55
55
  modules/superdocs.py,sha256=vMYyUbHU8zDkS1YMSDF7niDkT8d8FJFDcfIxSktCyGc,522
@@ -79,9 +79,9 @@ modules/unified_prompt_manager_qt.py,sha256=HkGUnH0wlfxt-hVe-nKCeWLyProYdefuuq2s
79
79
  modules/voice_commands.py,sha256=iBb-gjWxRMLhFH7-InSRjYJz1EIDBNA2Pog8V7TtJaY,38516
80
80
  modules/voice_dictation.py,sha256=QmitXfkG-vRt5hIQATjphHdhXfqmwhzcQcbXB6aRzIg,16386
81
81
  modules/voice_dictation_lite.py,sha256=jorY0BmWE-8VczbtGrWwt1zbnOctMoSlWOsQrcufBcc,9423
82
- supervertaler-1.9.185.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
83
- supervertaler-1.9.185.dist-info/METADATA,sha256=91u0TqLnZs1FiXLnbblIcBBw_90388vVDjHwjTKWi2Y,5725
84
- supervertaler-1.9.185.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
85
- supervertaler-1.9.185.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
86
- supervertaler-1.9.185.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
87
- supervertaler-1.9.185.dist-info/RECORD,,
82
+ supervertaler-1.9.187.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
83
+ supervertaler-1.9.187.dist-info/METADATA,sha256=9cptaoXjY9Z34yHQFE26tjGpuiEElxmslgd31e-kA70,5725
84
+ supervertaler-1.9.187.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
85
+ supervertaler-1.9.187.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
86
+ supervertaler-1.9.187.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
87
+ supervertaler-1.9.187.dist-info/RECORD,,