mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Merge pull request #46 from senolsun/fix-live-language-switch
Rebuild the settings window when the language changes
This commit is contained in:
+43
-4
@@ -1103,18 +1103,57 @@ class Dikte:
|
||||
|
||||
def open_settings(self):
|
||||
if self.settings_window is None:
|
||||
self.settings_window = SettingsWindow(self.conf, self.meetings)
|
||||
self.settings_window.applied.connect(self._apply_settings)
|
||||
self.settings_window.update_found.connect(self._found_update)
|
||||
self.settings_window.finished.connect(self._settings_closed)
|
||||
self._make_settings()
|
||||
self.settings_window.show()
|
||||
self.settings_window.raise_()
|
||||
self.settings_window.activateWindow()
|
||||
|
||||
def _make_settings(self):
|
||||
"""Build the window without showing it, so a caller that knows where
|
||||
it belongs can place it first."""
|
||||
self.settings_window = SettingsWindow(self.conf, self.meetings)
|
||||
self.settings_window.applied.connect(self._apply_settings)
|
||||
self.settings_window.language_changed.connect(self._reopen_settings)
|
||||
self.settings_window.update_found.connect(self._found_update)
|
||||
self.settings_window.finished.connect(self._settings_closed)
|
||||
|
||||
def _settings_closed(self, *_):
|
||||
# Don't drop the object while its own signal is still being delivered.
|
||||
QTimer.singleShot(0, lambda: setattr(self, "settings_window", None))
|
||||
|
||||
def _reopen_settings(self):
|
||||
"""Replace the settings window, so a language change reaches it too.
|
||||
|
||||
A save switches the language everywhere strings are made at the moment
|
||||
they are shown: the tray is rebuilt, the indicator and the message box
|
||||
translate as they speak. The settings window is the one place written
|
||||
once, at construction, so the window that took the new language is the
|
||||
one place still showing the old one. A fresh window comes up where the
|
||||
old one stood, on the same tab.
|
||||
"""
|
||||
old = self.settings_window
|
||||
if old is None:
|
||||
return
|
||||
tab = old.tabs.currentIndex()
|
||||
geometry = old.geometry()
|
||||
# Replaced rather than merely closed: left connected, _settings_closed
|
||||
# would drop the reference to the new window a moment after it is made.
|
||||
old.finished.disconnect(self._settings_closed)
|
||||
old.close()
|
||||
# No deleteLater: a daemon thread of the old window's may still be
|
||||
# running, and a closure holding self is what keeps the object alive
|
||||
# until the thread is done. Dropping the reference is how the ordinary
|
||||
# close path lets a window go, and it is enough here too.
|
||||
self.settings_window = None
|
||||
self._make_settings()
|
||||
# Placed and turned to the old tab before it is shown, so the new
|
||||
# window does not come up at the default size and jump.
|
||||
self.settings_window.setGeometry(geometry)
|
||||
self.settings_window.tabs.setCurrentIndex(tab)
|
||||
self.settings_window.show()
|
||||
self.settings_window.raise_()
|
||||
self.settings_window.activateWindow()
|
||||
|
||||
def _apply_local(self):
|
||||
"""Pass the local settings on, and hold the models ready if asked to.
|
||||
|
||||
|
||||
@@ -162,8 +162,6 @@ TR = {
|
||||
"Automatic (system)": "Otomatik (sistem)",
|
||||
"Turkish": "Türkçe",
|
||||
"English": "İngilizce",
|
||||
"Restart Dikte for the language change to reach every window.":
|
||||
"Dil değişikliğinin her pencereye işlemesi için Dikte'yi yeniden başlat.",
|
||||
"Microphone": "Mikrofon",
|
||||
"Default microphone": "Varsayılan mikrofon",
|
||||
"Speech language": "Konuşma dili",
|
||||
|
||||
+27
-3
@@ -23,6 +23,7 @@ from . import filetranscribe
|
||||
from . import ggml
|
||||
from . import hotkey
|
||||
from . import hub
|
||||
from . import i18n
|
||||
from . import ipc
|
||||
from . import meeting
|
||||
from . import paste
|
||||
@@ -515,6 +516,10 @@ class LocalModelBox(QGroupBox):
|
||||
|
||||
class SettingsWindow(QDialog):
|
||||
applied = pyqtSignal()
|
||||
# A save changed the interface language. Every label below is translated
|
||||
# as the window is built, so the change cannot reach this window: the
|
||||
# owner replaces it with a fresh one instead.
|
||||
language_changed = pyqtSignal()
|
||||
# A newer release this window's own check found, so that the tray icon
|
||||
# hears about it from here rather than waiting for its own next check.
|
||||
update_found = pyqtSignal(object)
|
||||
@@ -541,6 +546,8 @@ class SettingsWindow(QDialog):
|
||||
self._key_fields = {}
|
||||
self._testers = {}
|
||||
self._shown_provider = ""
|
||||
# What _save compares against to know a rebuild is due.
|
||||
self._built_language = i18n.language()
|
||||
# Where "Open the release page" goes: the release itself once a check
|
||||
# has named one, and the page that redirects to the newest until then.
|
||||
self._release_url = update.RELEASES_PAGE
|
||||
@@ -639,9 +646,6 @@ class SettingsWindow(QDialog):
|
||||
self.ui_language = QComboBox()
|
||||
for label, code in UI_LANGUAGES:
|
||||
self.ui_language.addItem(t(label), code)
|
||||
self.ui_language.setToolTip(
|
||||
t("Restart Dikte for the language change to reach every window.")
|
||||
)
|
||||
form.addRow(t("Interface language"), self.ui_language)
|
||||
|
||||
self.mic = QComboBox()
|
||||
@@ -1794,7 +1798,27 @@ class SettingsWindow(QDialog):
|
||||
print(f"dikte: could not trim the history ({exc})")
|
||||
self._load_history() # the trim may just have dropped rows from the list
|
||||
self.applied.emit()
|
||||
# conf.save() has switched the language t() speaks, so the message box
|
||||
# already answers in the new one; the labels around it were translated
|
||||
# when the window was built and stay behind. Asking for the rebuild
|
||||
# waits until the box is dismissed, so the window is not pulled out
|
||||
# from under a dialog it is holding up.
|
||||
QMessageBox.information(self, t("Dikte Settings"), t("Saved successfully."))
|
||||
if i18n.language() != self._built_language and not self._work_in_flight():
|
||||
self.language_changed.emit()
|
||||
|
||||
def _work_in_flight(self):
|
||||
"""A daemon thread of this window's is still running.
|
||||
|
||||
Replacing the window now would let it be collected, taking the C++
|
||||
side of the model boxes down with it, and the thread's next progress
|
||||
report would land on a deleted object. The stale labels stand until a
|
||||
later save finds the window quiet; _built_language keeps the old
|
||||
language, so that save asks for the rebuild by itself.
|
||||
"""
|
||||
return (self.transcriber.busy
|
||||
or self.local_whisper._downloading
|
||||
or self.local_llm._downloading)
|
||||
|
||||
@staticmethod
|
||||
def _select_data(combo, value):
|
||||
|
||||
@@ -240,6 +240,21 @@ class Settings(DikteTest):
|
||||
with self.subTest(key=key):
|
||||
self.assertEqual(stored[key], value)
|
||||
|
||||
def test_only_a_save_that_changed_the_language_says_so(self):
|
||||
# The owner answers language_changed by replacing the window, so a
|
||||
# save that left the language alone must keep quiet.
|
||||
i18n = settings_ui.i18n
|
||||
self.addCleanup(i18n.set_language, i18n.language())
|
||||
window = self.window(cfg.Config())
|
||||
heard = []
|
||||
window.language_changed.connect(lambda: heard.append(True))
|
||||
window._save()
|
||||
self.assertEqual(heard, [])
|
||||
other = "en" if i18n.language() == "tr" else "tr"
|
||||
window._select_data(window.ui_language, other)
|
||||
window._save()
|
||||
self.assertEqual(heard, [True])
|
||||
|
||||
def test_the_model_box_on_screen_belongs_to_whoever_cleans_up(self):
|
||||
"""An OpenRouter id and a Claude alias are not the same field."""
|
||||
window = self.window(cfg.Config())
|
||||
|
||||
Reference in New Issue
Block a user