supervertaler 1.9.175__py3-none-any.whl → 1.9.176b0__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 +276 -8
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/METADATA +1 -1
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/RECORD +7 -7
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/WHEEL +0 -0
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/entry_points.txt +0 -0
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/licenses/LICENSE +0 -0
- {supervertaler-1.9.175.dist-info → supervertaler-1.9.176b0.dist-info}/top_level.txt +0 -0
Supervertaler.py
CHANGED
|
@@ -34,7 +34,7 @@ License: MIT
|
|
|
34
34
|
"""
|
|
35
35
|
|
|
36
36
|
# Version Information.
|
|
37
|
-
__version__ = "1.9.
|
|
37
|
+
__version__ = "1.9.176-beta"
|
|
38
38
|
__phase__ = "0.9"
|
|
39
39
|
__release_date__ = "2026-01-28"
|
|
40
40
|
__edition__ = "Qt"
|
|
@@ -6435,13 +6435,10 @@ class SupervertalerQt(QMainWindow):
|
|
|
6435
6435
|
from PyQt6.QtCore import QTimer
|
|
6436
6436
|
QTimer.singleShot(2000, lambda: self._check_for_new_models(force=False)) # 2 second delay
|
|
6437
6437
|
|
|
6438
|
-
# First-run check - show
|
|
6439
|
-
if self._needs_data_location_dialog:
|
|
6438
|
+
# First-run check - show unified setup wizard
|
|
6439
|
+
if self._needs_data_location_dialog or not general_settings.get('first_run_completed', False):
|
|
6440
6440
|
from PyQt6.QtCore import QTimer
|
|
6441
|
-
QTimer.singleShot(300, self.
|
|
6442
|
-
elif not general_settings.get('first_run_completed', False):
|
|
6443
|
-
from PyQt6.QtCore import QTimer
|
|
6444
|
-
QTimer.singleShot(500, self._show_first_run_welcome)
|
|
6441
|
+
QTimer.singleShot(300, lambda: self._show_setup_wizard(is_first_run=True))
|
|
6445
6442
|
|
|
6446
6443
|
def _show_data_location_dialog(self):
|
|
6447
6444
|
"""Show dialog to let user choose their data folder location on first run."""
|
|
@@ -6672,7 +6669,273 @@ class SupervertalerQt(QMainWindow):
|
|
|
6672
6669
|
self.log("✅ First-run welcome shown (will show again next time)")
|
|
6673
6670
|
except Exception as e:
|
|
6674
6671
|
self.log(f"⚠️ First-run welcome error: {e}")
|
|
6675
|
-
|
|
6672
|
+
|
|
6673
|
+
def _show_setup_wizard(self, is_first_run: bool = False):
|
|
6674
|
+
"""
|
|
6675
|
+
Show unified setup wizard that combines data folder selection and features intro.
|
|
6676
|
+
|
|
6677
|
+
Args:
|
|
6678
|
+
is_first_run: If True, this is an automatic first-run trigger. If False, user
|
|
6679
|
+
manually invoked from menu (skip data folder if already configured).
|
|
6680
|
+
"""
|
|
6681
|
+
try:
|
|
6682
|
+
from PyQt6.QtWidgets import (QDialog, QVBoxLayout, QHBoxLayout, QLabel,
|
|
6683
|
+
QPushButton, QLineEdit, QFileDialog, QStackedWidget,
|
|
6684
|
+
QWidget, QFrame, QCheckBox)
|
|
6685
|
+
from PyQt6.QtCore import Qt
|
|
6686
|
+
|
|
6687
|
+
dialog = QDialog(self)
|
|
6688
|
+
dialog.setWindowTitle("Supervertaler Setup Wizard")
|
|
6689
|
+
dialog.setMinimumWidth(600)
|
|
6690
|
+
dialog.setMinimumHeight(450)
|
|
6691
|
+
dialog.setModal(True)
|
|
6692
|
+
|
|
6693
|
+
main_layout = QVBoxLayout(dialog)
|
|
6694
|
+
main_layout.setSpacing(15)
|
|
6695
|
+
main_layout.setContentsMargins(20, 20, 20, 20)
|
|
6696
|
+
|
|
6697
|
+
# Stacked widget for wizard pages
|
|
6698
|
+
stacked = QStackedWidget()
|
|
6699
|
+
|
|
6700
|
+
# Determine if we need to show data folder page
|
|
6701
|
+
show_data_folder_page = is_first_run and self._needs_data_location_dialog
|
|
6702
|
+
|
|
6703
|
+
# ==================== PAGE 1: Data Folder Selection ====================
|
|
6704
|
+
page1 = QWidget()
|
|
6705
|
+
page1_layout = QVBoxLayout(page1)
|
|
6706
|
+
page1_layout.setSpacing(15)
|
|
6707
|
+
|
|
6708
|
+
# Step indicator
|
|
6709
|
+
step1_indicator = QLabel("<span style='color: #888;'>Step 1 of 2</span>")
|
|
6710
|
+
page1_layout.addWidget(step1_indicator)
|
|
6711
|
+
|
|
6712
|
+
# Title
|
|
6713
|
+
page1_title = QLabel("<h2>📁 Choose Your Data Folder</h2>")
|
|
6714
|
+
page1_layout.addWidget(page1_title)
|
|
6715
|
+
|
|
6716
|
+
# Explanation
|
|
6717
|
+
page1_msg = QLabel(
|
|
6718
|
+
"Supervertaler stores your data in a folder of your choice:<br><br>"
|
|
6719
|
+
"• <b>API keys</b> – Your LLM provider credentials<br>"
|
|
6720
|
+
"• <b>Translation memories</b> – Reusable translation pairs<br>"
|
|
6721
|
+
"• <b>Glossaries</b> – Terminology databases<br>"
|
|
6722
|
+
"• <b>Prompts</b> – Custom AI prompts<br>"
|
|
6723
|
+
"• <b>Settings</b> – Application configuration<br><br>"
|
|
6724
|
+
"Choose a location that's easy to find and backup."
|
|
6725
|
+
)
|
|
6726
|
+
page1_msg.setWordWrap(True)
|
|
6727
|
+
page1_layout.addWidget(page1_msg)
|
|
6728
|
+
|
|
6729
|
+
# Path input with browse button
|
|
6730
|
+
path_layout = QHBoxLayout()
|
|
6731
|
+
path_edit = QLineEdit()
|
|
6732
|
+
default_path = get_default_user_data_path()
|
|
6733
|
+
path_edit.setText(str(default_path))
|
|
6734
|
+
path_edit.setMinimumWidth(350)
|
|
6735
|
+
path_layout.addWidget(path_edit)
|
|
6736
|
+
|
|
6737
|
+
browse_btn = QPushButton("Browse...")
|
|
6738
|
+
def browse_folder():
|
|
6739
|
+
folder = QFileDialog.getExistingDirectory(
|
|
6740
|
+
dialog,
|
|
6741
|
+
"Choose Data Folder",
|
|
6742
|
+
str(Path.home())
|
|
6743
|
+
)
|
|
6744
|
+
if folder:
|
|
6745
|
+
folder_path = Path(folder)
|
|
6746
|
+
if folder_path.name != "Supervertaler":
|
|
6747
|
+
folder_path = folder_path / "Supervertaler"
|
|
6748
|
+
path_edit.setText(str(folder_path))
|
|
6749
|
+
|
|
6750
|
+
browse_btn.clicked.connect(browse_folder)
|
|
6751
|
+
path_layout.addWidget(browse_btn)
|
|
6752
|
+
page1_layout.addLayout(path_layout)
|
|
6753
|
+
|
|
6754
|
+
# Tip
|
|
6755
|
+
page1_tip = QLabel(
|
|
6756
|
+
"💡 <b>Tip:</b> The default location is in your home folder, "
|
|
6757
|
+
"making it easy to find and backup."
|
|
6758
|
+
)
|
|
6759
|
+
page1_tip.setWordWrap(True)
|
|
6760
|
+
page1_tip.setStyleSheet("color: #666;")
|
|
6761
|
+
page1_layout.addWidget(page1_tip)
|
|
6762
|
+
|
|
6763
|
+
page1_layout.addStretch()
|
|
6764
|
+
stacked.addWidget(page1)
|
|
6765
|
+
|
|
6766
|
+
# ==================== PAGE 2: Features Introduction ====================
|
|
6767
|
+
page2 = QWidget()
|
|
6768
|
+
page2_layout = QVBoxLayout(page2)
|
|
6769
|
+
page2_layout.setSpacing(15)
|
|
6770
|
+
|
|
6771
|
+
# Step indicator
|
|
6772
|
+
step2_label = "Step 2 of 2" if show_data_folder_page else "Setup"
|
|
6773
|
+
step2_indicator = QLabel(f"<span style='color: #888;'>{step2_label}</span>")
|
|
6774
|
+
page2_layout.addWidget(step2_indicator)
|
|
6775
|
+
|
|
6776
|
+
# Data folder info (shown when skipping page 1)
|
|
6777
|
+
if not show_data_folder_page:
|
|
6778
|
+
from PyQt6.QtGui import QDesktopServices
|
|
6779
|
+
from PyQt6.QtCore import QUrl
|
|
6780
|
+
|
|
6781
|
+
data_folder_path = str(self.user_data_path)
|
|
6782
|
+
data_folder_info = QLabel(
|
|
6783
|
+
f"<b>📁 Data Folder:</b> <a href='file:///{data_folder_path}' "
|
|
6784
|
+
f"style='color: #3b82f6;'>{data_folder_path}</a><br>"
|
|
6785
|
+
"<span style='color: #666; font-size: 0.9em;'>"
|
|
6786
|
+
"Your settings, TMs, glossaries and prompts are stored here. "
|
|
6787
|
+
"Change in Settings → General.</span>"
|
|
6788
|
+
)
|
|
6789
|
+
data_folder_info.setWordWrap(True)
|
|
6790
|
+
data_folder_info.setTextFormat(Qt.TextFormat.RichText)
|
|
6791
|
+
data_folder_info.setOpenExternalLinks(False) # Handle clicks ourselves
|
|
6792
|
+
data_folder_info.linkActivated.connect(
|
|
6793
|
+
lambda url: QDesktopServices.openUrl(QUrl.fromLocalFile(data_folder_path))
|
|
6794
|
+
)
|
|
6795
|
+
data_folder_info.setStyleSheet(
|
|
6796
|
+
"background: #f0f4ff; padding: 12px; border-radius: 6px; "
|
|
6797
|
+
"border-left: 4px solid #3b82f6; margin-bottom: 10px;"
|
|
6798
|
+
)
|
|
6799
|
+
page2_layout.addWidget(data_folder_info)
|
|
6800
|
+
|
|
6801
|
+
# Title
|
|
6802
|
+
page2_title = QLabel("<h2>✨ Modular Features</h2>")
|
|
6803
|
+
page2_layout.addWidget(page2_title)
|
|
6804
|
+
|
|
6805
|
+
# Message
|
|
6806
|
+
page2_msg = QLabel(
|
|
6807
|
+
"Supervertaler uses a <b>modular architecture</b> – you can install "
|
|
6808
|
+
"only the features you need.<br><br>"
|
|
6809
|
+
"<b>Core features</b> (always available):<br>"
|
|
6810
|
+
"• AI translation with OpenAI, Claude, Gemini, Ollama<br>"
|
|
6811
|
+
"• Translation Memory and Glossaries<br>"
|
|
6812
|
+
"• XLIFF, SDLXLIFF, memoQ support<br>"
|
|
6813
|
+
"• Basic spellchecking<br><br>"
|
|
6814
|
+
"<b>Optional features</b> (install via pip):<br>"
|
|
6815
|
+
"• <code>openai-whisper</code> – Local voice dictation (no API needed)<br><br>"
|
|
6816
|
+
"You can view and manage features in <b>Settings → Features</b>."
|
|
6817
|
+
)
|
|
6818
|
+
page2_msg.setWordWrap(True)
|
|
6819
|
+
page2_msg.setTextFormat(Qt.TextFormat.RichText)
|
|
6820
|
+
page2_layout.addWidget(page2_msg)
|
|
6821
|
+
|
|
6822
|
+
# Checkbox
|
|
6823
|
+
dont_show_checkbox = CheckmarkCheckBox("Don't show this wizard on startup")
|
|
6824
|
+
dont_show_checkbox.setChecked(True)
|
|
6825
|
+
page2_layout.addWidget(dont_show_checkbox)
|
|
6826
|
+
|
|
6827
|
+
# Open Features tab checkbox
|
|
6828
|
+
open_features_checkbox = CheckmarkCheckBox("Open Features tab after closing")
|
|
6829
|
+
open_features_checkbox.setChecked(True)
|
|
6830
|
+
page2_layout.addWidget(open_features_checkbox)
|
|
6831
|
+
|
|
6832
|
+
page2_layout.addStretch()
|
|
6833
|
+
stacked.addWidget(page2)
|
|
6834
|
+
|
|
6835
|
+
main_layout.addWidget(stacked)
|
|
6836
|
+
|
|
6837
|
+
# ==================== Navigation Buttons ====================
|
|
6838
|
+
nav_layout = QHBoxLayout()
|
|
6839
|
+
|
|
6840
|
+
back_btn = QPushButton("← Back")
|
|
6841
|
+
back_btn.setVisible(False) # Hidden on first page
|
|
6842
|
+
|
|
6843
|
+
next_btn = QPushButton("Next →")
|
|
6844
|
+
finish_btn = QPushButton("Finish")
|
|
6845
|
+
finish_btn.setVisible(False)
|
|
6846
|
+
finish_btn.setDefault(True)
|
|
6847
|
+
|
|
6848
|
+
# Use Default button (only on page 1)
|
|
6849
|
+
default_btn = QPushButton("Use Default")
|
|
6850
|
+
default_btn.clicked.connect(lambda: path_edit.setText(str(default_path)))
|
|
6851
|
+
|
|
6852
|
+
nav_layout.addWidget(default_btn)
|
|
6853
|
+
nav_layout.addStretch()
|
|
6854
|
+
nav_layout.addWidget(back_btn)
|
|
6855
|
+
nav_layout.addWidget(next_btn)
|
|
6856
|
+
nav_layout.addWidget(finish_btn)
|
|
6857
|
+
|
|
6858
|
+
main_layout.addLayout(nav_layout)
|
|
6859
|
+
|
|
6860
|
+
# Track chosen path for later
|
|
6861
|
+
chosen_path_holder = [None]
|
|
6862
|
+
|
|
6863
|
+
def go_to_page(page_index):
|
|
6864
|
+
stacked.setCurrentIndex(page_index)
|
|
6865
|
+
if page_index == 0:
|
|
6866
|
+
back_btn.setVisible(False)
|
|
6867
|
+
next_btn.setVisible(True)
|
|
6868
|
+
finish_btn.setVisible(False)
|
|
6869
|
+
default_btn.setVisible(True)
|
|
6870
|
+
else:
|
|
6871
|
+
back_btn.setVisible(show_data_folder_page)
|
|
6872
|
+
next_btn.setVisible(False)
|
|
6873
|
+
finish_btn.setVisible(True)
|
|
6874
|
+
default_btn.setVisible(False)
|
|
6875
|
+
|
|
6876
|
+
def on_next():
|
|
6877
|
+
# Save the data folder choice
|
|
6878
|
+
chosen_path = Path(path_edit.text())
|
|
6879
|
+
chosen_path_holder[0] = chosen_path
|
|
6880
|
+
|
|
6881
|
+
# Create the folder and save config
|
|
6882
|
+
chosen_path.mkdir(parents=True, exist_ok=True)
|
|
6883
|
+
save_user_data_path(chosen_path)
|
|
6884
|
+
|
|
6885
|
+
# Update our path if different
|
|
6886
|
+
if chosen_path != self.user_data_path:
|
|
6887
|
+
self.user_data_path = chosen_path
|
|
6888
|
+
self._reinitialize_with_new_data_path()
|
|
6889
|
+
else:
|
|
6890
|
+
if hasattr(self, 'db_manager') and self.db_manager and not self.db_manager.connection:
|
|
6891
|
+
self.db_manager.connect()
|
|
6892
|
+
|
|
6893
|
+
self.log(f"📁 Data folder set to: {chosen_path}")
|
|
6894
|
+
go_to_page(1)
|
|
6895
|
+
|
|
6896
|
+
def on_back():
|
|
6897
|
+
go_to_page(0)
|
|
6898
|
+
|
|
6899
|
+
def on_finish():
|
|
6900
|
+
# Save first_run preference
|
|
6901
|
+
if dont_show_checkbox.isChecked():
|
|
6902
|
+
settings = self.load_general_settings()
|
|
6903
|
+
settings['first_run_completed'] = True
|
|
6904
|
+
self.save_general_settings(settings)
|
|
6905
|
+
self.log("✅ Setup wizard completed (won't show again on startup)")
|
|
6906
|
+
else:
|
|
6907
|
+
self.log("✅ Setup wizard shown (will show again next time)")
|
|
6908
|
+
|
|
6909
|
+
dialog.accept()
|
|
6910
|
+
|
|
6911
|
+
# Navigate to Features tab if checkbox is checked
|
|
6912
|
+
if open_features_checkbox.isChecked():
|
|
6913
|
+
self.main_tabs.setCurrentIndex(4) # Settings tab
|
|
6914
|
+
if hasattr(self, 'settings_tabs'):
|
|
6915
|
+
for i in range(self.settings_tabs.count()):
|
|
6916
|
+
if "Features" in self.settings_tabs.tabText(i):
|
|
6917
|
+
self.settings_tabs.setCurrentIndex(i)
|
|
6918
|
+
break
|
|
6919
|
+
|
|
6920
|
+
back_btn.clicked.connect(on_back)
|
|
6921
|
+
next_btn.clicked.connect(on_next)
|
|
6922
|
+
finish_btn.clicked.connect(on_finish)
|
|
6923
|
+
|
|
6924
|
+
# Start on appropriate page
|
|
6925
|
+
if show_data_folder_page:
|
|
6926
|
+
go_to_page(0)
|
|
6927
|
+
else:
|
|
6928
|
+
# Skip to features page if data folder already configured
|
|
6929
|
+
go_to_page(1)
|
|
6930
|
+
step2_indicator.setText("<span style='color: #888;'>Supervertaler Setup</span>")
|
|
6931
|
+
|
|
6932
|
+
dialog.exec()
|
|
6933
|
+
|
|
6934
|
+
except Exception as e:
|
|
6935
|
+
self.log(f"⚠️ Setup wizard error: {e}")
|
|
6936
|
+
import traceback
|
|
6937
|
+
traceback.print_exc()
|
|
6938
|
+
|
|
6676
6939
|
def _check_for_new_models(self, force: bool = False):
|
|
6677
6940
|
"""
|
|
6678
6941
|
Check for new LLM models from providers
|
|
@@ -7936,6 +8199,11 @@ class SupervertalerQt(QMainWindow):
|
|
|
7936
8199
|
superdocs_action.triggered.connect(lambda: self._open_url("https://supervertaler.gitbook.io/superdocs/"))
|
|
7937
8200
|
help_menu.addAction(superdocs_action)
|
|
7938
8201
|
|
|
8202
|
+
setup_wizard_action = QAction("🚀 Setup Wizard...", self)
|
|
8203
|
+
setup_wizard_action.setToolTip("Run the initial setup wizard (data folder location, features overview)")
|
|
8204
|
+
setup_wizard_action.triggered.connect(lambda: self._show_setup_wizard(is_first_run=False))
|
|
8205
|
+
help_menu.addAction(setup_wizard_action)
|
|
8206
|
+
|
|
7939
8207
|
help_menu.addSeparator()
|
|
7940
8208
|
|
|
7941
8209
|
shortcuts_action = QAction("⌨️ Keyboard Shortcuts", self)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: supervertaler
|
|
3
|
-
Version: 1.9.
|
|
3
|
+
Version: 1.9.176b0
|
|
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=
|
|
1
|
+
Supervertaler.py,sha256=ABqaS7k80j4w3EiJr52ogQVIJRAFFOD3NpaeDbzWX6k,2318994
|
|
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
|
|
@@ -77,9 +77,9 @@ modules/unified_prompt_manager_qt.py,sha256=U89UFGG-M7BLetoaLAlma0x-n8SIyx682DhS
|
|
|
77
77
|
modules/voice_commands.py,sha256=iBb-gjWxRMLhFH7-InSRjYJz1EIDBNA2Pog8V7TtJaY,38516
|
|
78
78
|
modules/voice_dictation.py,sha256=QmitXfkG-vRt5hIQATjphHdhXfqmwhzcQcbXB6aRzIg,16386
|
|
79
79
|
modules/voice_dictation_lite.py,sha256=jorY0BmWE-8VczbtGrWwt1zbnOctMoSlWOsQrcufBcc,9423
|
|
80
|
-
supervertaler-1.9.
|
|
81
|
-
supervertaler-1.9.
|
|
82
|
-
supervertaler-1.9.
|
|
83
|
-
supervertaler-1.9.
|
|
84
|
-
supervertaler-1.9.
|
|
85
|
-
supervertaler-1.9.
|
|
80
|
+
supervertaler-1.9.176b0.dist-info/licenses/LICENSE,sha256=m28u-4qL5nXIWnJ6xlQVw__H30rWFtRK3pCOais2OuY,1092
|
|
81
|
+
supervertaler-1.9.176b0.dist-info/METADATA,sha256=NXnmveUpuH50y_2kAdkEavCbLiRpDYAUSIIc7YK0d-8,5727
|
|
82
|
+
supervertaler-1.9.176b0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
83
|
+
supervertaler-1.9.176b0.dist-info/entry_points.txt,sha256=NP4hiCvx-_30YYKqgr-jfJYQvHr1qTYBMfoVmKIXSM8,53
|
|
84
|
+
supervertaler-1.9.176b0.dist-info/top_level.txt,sha256=9tUHBYUSfaE4S2E4W3eavJsDyYymkwLfeWAHHAPT6Dk,22
|
|
85
|
+
supervertaler-1.9.176b0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|