The Input Device dropdown has a fixed width and cuts labels off at about 18 characters. Raw ALSA names such as "sof-hda-dsp: - (hw:0,6)" therefore all look like "sof-hda-dsp: - (h…", and the tooltip always showed the same generic text, so there was no way to tell which entry was selected. The tooltip now shows the full label of the selected device. It updates when the list is filled and every time the selection changes, and goes back to the generic hint for System Default.
This commit is contained in:
@@ -2140,6 +2140,18 @@ def _combo_chrome(combo: Gtk.Widget, tooltip: Optional[str] = None) -> None:
|
||||
_prevent_scroll_on_hover(combo)
|
||||
|
||||
|
||||
_AUDIO_DEVICE_TOOLTIP = "Select the microphone to use for voice recognition"
|
||||
|
||||
|
||||
def _sync_audio_device_tooltip(combo: Gtk.ComboBoxText) -> None:
|
||||
"""Show the selected microphone's full name, which the fixed-width combo truncates."""
|
||||
label = combo.get_active_text()
|
||||
if not label or combo.get_active_id() in (None, "-1"):
|
||||
combo.set_tooltip_text(_AUDIO_DEVICE_TOOLTIP)
|
||||
else:
|
||||
combo.set_tooltip_text(label)
|
||||
|
||||
|
||||
def _new_spin(
|
||||
lower: float, upper: float, step: float, digits: int, tooltip: Optional[str] = None
|
||||
) -> Gtk.SpinButton:
|
||||
@@ -3137,7 +3149,7 @@ class SettingsDialog(AboutSectionMixin):
|
||||
self.audio_device_combo = Gtk.ComboBoxText()
|
||||
_combo_chrome(
|
||||
self.audio_device_combo,
|
||||
tooltip="Select the microphone to use for voice recognition",
|
||||
tooltip=_AUDIO_DEVICE_TOOLTIP,
|
||||
)
|
||||
|
||||
refresh_btn = Gtk.Button.new_from_icon_name("view-refresh-symbolic", Gtk.IconSize.BUTTON)
|
||||
@@ -9925,6 +9937,7 @@ For now, the engine has been reverted to VOSK."""
|
||||
if self.speech_engine is not None:
|
||||
self.speech_engine.set_audio_device(None, None)
|
||||
|
||||
_sync_audio_device_tooltip(self.audio_device_combo)
|
||||
logger.info(f"Found {len(devices)} audio input devices")
|
||||
|
||||
def _on_refresh_audio_devices(self, widget):
|
||||
@@ -9934,6 +9947,7 @@ For now, the engine has been reverted to VOSK."""
|
||||
|
||||
def _on_audio_device_changed(self, widget):
|
||||
"""Handle changes in the selected audio device."""
|
||||
_sync_audio_device_tooltip(self.audio_device_combo)
|
||||
if self._initializing:
|
||||
return
|
||||
|
||||
|
||||
@@ -633,6 +633,52 @@ class TestSettingsPersistsServerName:
|
||||
dialog.audio_device_combo.set_active_id.assert_called_with(str(PULSE_INDEX_BASE - 1))
|
||||
|
||||
|
||||
class TestAudioDeviceTooltip:
|
||||
"""The fixed-width dropdown truncates long names; the tooltip shows them whole (#1029)."""
|
||||
|
||||
_SOF = "sof-hda-dsp: - (hw:0,6)"
|
||||
|
||||
def _combo(self, device_id: Optional[str], label: Optional[str]) -> MagicMock:
|
||||
combo = MagicMock()
|
||||
combo.get_active_id.return_value = device_id
|
||||
combo.get_active_text.return_value = label
|
||||
return combo
|
||||
|
||||
def test_choosing_a_device_shows_its_full_name_in_the_tooltip(self) -> None:
|
||||
settings_dialog = _load_settings_dialog()
|
||||
dialog = MagicMock(_initializing=False, _pulse_source_names={})
|
||||
dialog.audio_device_combo = self._combo("1", self._SOF)
|
||||
settings_dialog.SettingsDialog._on_audio_device_changed(dialog, None)
|
||||
dialog.audio_device_combo.set_tooltip_text.assert_called_with(self._SOF)
|
||||
|
||||
def test_system_default_keeps_the_generic_tooltip(self) -> None:
|
||||
settings_dialog = _load_settings_dialog()
|
||||
dialog = MagicMock(_initializing=False, _pulse_source_names={})
|
||||
dialog.audio_device_combo = self._combo("-1", "System Default")
|
||||
settings_dialog.SettingsDialog._on_audio_device_changed(dialog, None)
|
||||
dialog.audio_device_combo.set_tooltip_text.assert_called_with(
|
||||
"Select the microphone to use for voice recognition"
|
||||
)
|
||||
|
||||
def test_populating_shows_the_saved_device_in_the_tooltip(self) -> None:
|
||||
"""The saved device is selected before the change handler is wired up."""
|
||||
settings_dialog = _load_settings_dialog()
|
||||
dialog = MagicMock()
|
||||
dialog.config_manager.get_optional_int.return_value = 1
|
||||
dialog.config_manager.get.return_value = self._SOF
|
||||
dialog.audio_device_combo = self._combo("1", self._SOF)
|
||||
devices = [(0, "sof-hda-dsp: - (hw:0,0)", False), (1, self._SOF, False)]
|
||||
with (
|
||||
patch.object(settings_dialog, "get_pulse_sources", return_value=[]),
|
||||
patch(
|
||||
"vocalinux.speech_recognition.recognition_manager.get_audio_input_devices",
|
||||
return_value=devices,
|
||||
),
|
||||
):
|
||||
settings_dialog.SettingsDialog._populate_audio_devices(dialog)
|
||||
dialog.audio_device_combo.set_tooltip_text.assert_called_with(self._SOF)
|
||||
|
||||
|
||||
def _load_settings_dialog() -> ModuleType:
|
||||
"""Import settings_dialog with real GTK base classes so its methods are callable.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user