v1.0.1 Feature Update and Polish
Full Changelog: [New Features] - Added Native Translation Mode: - Whisper model now fully supports Translating any language to English - Added 'task' and 'language' parameters to Transcriber core - Dual Hotkey Support: - Added separate Global Hotkeys for Transcribe (default F8) and Translate (default F10) - Both hotkeys are fully customizable in Settings - Engine dynamically switches modes based on which key is pressed [UI/UX Improvements] - Settings Window: - Widened Hotkey Input fields (240px) to accommodate long combinations - Added Pretty-Printing for hotkey sequences (e.g. 'ctrl+f9' display as 'Ctrl + F9') - Replaced Country Code dropdown with Full Language Names (99+ languages) - Made Language Dropdown scrollable (max height 300px) to prevent screen overflow - Removed redundant 'Task' selector (replaced by dedicated hotkeys) - System Tray: - Tooltip now displays both Transcribe and Translate hotkeys - Tooltip hotkeys are formatted readably [Core & Performance] - Bootstrapper: - Implemented Smart Incremental Sync - Now checks filesize and content hash before copying files - Drastically reduces startup time for subsequent runs - Preserves user settings.json during updates - Backend: - Fixed HotkeyManager to support dynamic configuration keys - Fixed Language Lock: selecting a language now correctly forces the model to use it - Refactored bridge/main connection for language list handling
This commit is contained in:
@@ -245,6 +245,26 @@ class UIBridge(QObject):
|
||||
|
||||
# --- Methods called from QML ---
|
||||
|
||||
@Slot(result=list)
|
||||
def get_supported_languages(self):
|
||||
from src.core.languages import get_language_names
|
||||
return get_language_names()
|
||||
|
||||
@Slot(str)
|
||||
def set_language_by_name(self, name):
|
||||
from src.core.languages import get_code_by_name
|
||||
from src.core.config import ConfigManager
|
||||
code = get_code_by_name(name)
|
||||
ConfigManager().set("language", code)
|
||||
self.settingChanged.emit("language", code)
|
||||
|
||||
@Slot(result=str)
|
||||
def get_current_language_name(self):
|
||||
from src.core.languages import get_name_by_code
|
||||
from src.core.config import ConfigManager
|
||||
code = ConfigManager().get("language")
|
||||
return get_name_by_code(code)
|
||||
|
||||
@Slot(str, result='QVariant')
|
||||
def getSetting(self, key):
|
||||
from src.core.config import ConfigManager
|
||||
|
||||
@@ -100,7 +100,7 @@ ComboBox {
|
||||
popup: Popup {
|
||||
y: control.height - 1
|
||||
width: control.width
|
||||
implicitHeight: contentItem.implicitHeight
|
||||
implicitHeight: Math.min(contentItem.implicitHeight, 300)
|
||||
padding: 5
|
||||
|
||||
contentItem: ListView {
|
||||
|
||||
@@ -25,7 +25,7 @@ Rectangle {
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: control.recording ? "Listening..." : (control.currentSequence || "None")
|
||||
text: control.recording ? "Listening..." : (formatSequence(control.currentSequence) || "None")
|
||||
color: control.recording ? SettingsStyle.accent : (control.currentSequence ? "#ffffff" : "#808080")
|
||||
font.family: "JetBrains Mono"
|
||||
font.pixelSize: 13
|
||||
@@ -72,6 +72,23 @@ Rectangle {
|
||||
if (!activeFocus) control.recording = false
|
||||
}
|
||||
|
||||
function formatSequence(seq) {
|
||||
if (!seq) return ""
|
||||
var parts = seq.split("+")
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var p = parts[i]
|
||||
// Standardize modifiers
|
||||
if (p === "ctrl") parts[i] = "Ctrl"
|
||||
else if (p === "alt") parts[i] = "Alt"
|
||||
else if (p === "shift") parts[i] = "Shift"
|
||||
else if (p === "win") parts[i] = "Win"
|
||||
else if (p === "esc") parts[i] = "Esc"
|
||||
// Capitalize F-keys and others (e.g. f8 -> F8, space -> Space)
|
||||
else parts[i] = p.charAt(0).toUpperCase() + p.slice(1)
|
||||
}
|
||||
return parts.join(" + ")
|
||||
}
|
||||
|
||||
function getKeyName(key, text) {
|
||||
// F-Keys
|
||||
if (key >= Qt.Key_F1 && key <= Qt.Key_F35) return "f" + (key - Qt.Key_F1 + 1)
|
||||
|
||||
@@ -314,14 +314,24 @@ Window {
|
||||
spacing: 0
|
||||
|
||||
ModernSettingsItem {
|
||||
label: "Global Hotkey"
|
||||
description: "Press to record a new shortcut (e.g. Ctrl+Space)"
|
||||
label: "Global Hotkey (Transcribe)"
|
||||
description: "Press to record a new shortcut (e.g. F9)"
|
||||
control: ModernKeySequenceRecorder {
|
||||
Layout.preferredWidth: 200
|
||||
implicitWidth: 240
|
||||
currentSequence: ui.getSetting("hotkey")
|
||||
onSequenceChanged: (seq) => ui.setSetting("hotkey", seq)
|
||||
}
|
||||
}
|
||||
|
||||
ModernSettingsItem {
|
||||
label: "Global Hotkey (Translate)"
|
||||
description: "Press to record a new shortcut (e.g. F10)"
|
||||
control: ModernKeySequenceRecorder {
|
||||
implicitWidth: 240
|
||||
currentSequence: ui.getSetting("hotkey_translate")
|
||||
onSequenceChanged: (seq) => ui.setSetting("hotkey_translate", seq)
|
||||
}
|
||||
}
|
||||
|
||||
ModernSettingsItem {
|
||||
label: "Run on Startup"
|
||||
@@ -742,15 +752,17 @@ Window {
|
||||
|
||||
ModernSettingsItem {
|
||||
label: "Language"
|
||||
description: "Force language or Auto-detect"
|
||||
description: "Spoken language to transcribe"
|
||||
control: ModernComboBox {
|
||||
width: 140
|
||||
model: ["auto", "en", "fr", "de", "es", "it", "ja", "zh", "ru"]
|
||||
currentIndex: model.indexOf(ui.getSetting("language"))
|
||||
onActivated: ui.setSetting("language", currentText)
|
||||
Layout.preferredWidth: 200
|
||||
model: ui.get_supported_languages()
|
||||
currentIndex: model.indexOf(ui.get_current_language_name())
|
||||
onActivated: (index) => ui.set_language_by_name(currentText)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Task selector removed as per user request (Hotkeys handle this now)
|
||||
|
||||
ModernSettingsItem {
|
||||
label: "Compute Device"
|
||||
description: "Hardware acceleration (CUDA requires NVidia GPU)"
|
||||
|
||||
Reference in New Issue
Block a user