diff --git a/dikte/settings_ui.py b/dikte/settings_ui.py index 56771f8..9d43d3d 100644 --- a/dikte/settings_ui.py +++ b/dikte/settings_ui.py @@ -886,13 +886,13 @@ class SettingsWindow(QDialog): "spends that once instead of on the first dictation, at the cost of " "the memory it sits in.")) self.local_threads = QSpinBox() - self.local_threads.setRange(0, 64) + max_threads = max(1, os.cpu_count() or 1) + self.local_threads.setRange(0, max_threads) self.local_threads.setSpecialValueText(t("Automatic")) - # A spin box asks for room for its numbers, and 64 is two characters: - # the word standing in for zero is what actually has to fit, and on - # macOS, where the stepper sits inside the frame, it does not. Widened - # to the word rather than to a number picked by eye, so that it still - # fits once the word is "Otomatik". + # A spin box asks for room for its numbers, and the word standing in for + # zero is what actually has to fit, and on macOS, where the stepper sits + # inside the frame, it does not. Widened to the word rather than to a + # number picked by eye, so that it still fits once the word is "Otomatik". self.local_threads.setMinimumWidth( self.local_threads.fontMetrics() .horizontalAdvance(t("Automatic")) + 56) diff --git a/tests/test_ui.py b/tests/test_ui.py index 6273447..7ccc900 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -72,7 +72,7 @@ CHANGED = { "local_model": "ggml-small.bin", "local_gpu": False, "local_preload": False, - "local_threads": 6, + "local_threads": 1, "local_llm_model": "gemma-3-4b-it-Q4_K_M.gguf", "local_llm_repo": "ggml-org/gemma-4-E2B-it-GGUF", "local_llm_gpu": False, @@ -1257,3 +1257,15 @@ class LocalModels(DikteTest): # isHidden rather than isVisible: the window itself is never # shown in a test, so nothing in it is ever visible. self.assertEqual(other.isHidden(), name != chosen) + + def test_local_threads_range_is_bounded_by_cpu_count(self): + with mock.patch("os.cpu_count", return_value=8): + window = self.window(cfg.Config()) + self.assertEqual(window.local_threads.minimum(), 0) + self.assertEqual(window.local_threads.maximum(), 8) + + def test_local_threads_range_has_safe_minimum_when_cpu_count_is_none(self): + with mock.patch("os.cpu_count", return_value=None): + window = self.window(cfg.Config()) + self.assertEqual(window.local_threads.minimum(), 0) + self.assertEqual(window.local_threads.maximum(), 1)